diff --git a/.github/SECURITY.md b/.github/SECURITY.md index dd673d4289e770443d3955e9dc59f67478ae07ac..800b8aff2652f3e35a0fdb582ad437e0892a5fbc 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -15,7 +15,7 @@ If you discover a security vulnerability within Laravel, please send an email to ``` -----BEGIN PGP PUBLIC KEY BLOCK----- Version: OpenPGP v2.0.8 -Comment: https://sela.io/pgp/ +Comment: Report Security Vulnerabilities to taylor@laravel.com xsFNBFugFSQBEACxEKhIY9IoJzcouVTIYKJfWFGvwFgbRjQWBiH3QdHId5vCrbWo s2l+4Rv03gMG+yHLJ3rWElnNdRaNdQv59+lShrZF7Bvu7Zvc0mMNmFOM/mQ/K2Lt diff --git a/CHANGELOG.md b/CHANGELOG.md index f336ecfd1e86506821ed7fe8538a5aeebff6ef71..272a76345b1259d10672e68b987ef09a271b918a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Release Notes -## [Unreleased](https://github.com/laravel/prompts/compare/v0.1.23...main) +## [Unreleased](https://github.com/laravel/prompts/compare/v0.1.24...main) + +## [v0.1.24](https://github.com/laravel/prompts/compare/v0.1.23...v0.1.24) - 2024-06-17 + +* Allow re-rendering during progress callback by [@jessarcher](https://github.com/jessarcher) in https://github.com/laravel/prompts/pull/155 ## [v0.1.23](https://github.com/laravel/prompts/compare/v0.1.22...v0.1.23) - 2024-05-27 diff --git a/playground/text.php b/playground/text.php index 2f596d1802c8feffbc31d3213257b785540fcc2c..ea13970fc1e41a3eda63c34df49cb0838b284f51 100644 --- a/playground/text.php +++ b/playground/text.php @@ -13,6 +13,7 @@ $email = text( default => null, }, hint: 'We will never share your email address with anyone else.', + transform: fn ($value) => strtolower($value), ); var_dump($email); diff --git a/playground/textarea.php b/playground/textarea.php index 070305f2b981d46fa69b34c7c4e345d2f7431da0..9e498cef69263e4cf7f53ef55cf06f9f5e2acff7 100644 --- a/playground/textarea.php +++ b/playground/textarea.php @@ -4,11 +4,11 @@ use function Laravel\Prompts\textarea; require __DIR__.'/../vendor/autoload.php'; -$email = textarea( +$story = textarea( label: 'Tell me a story', placeholder: 'Weave me a tale', ); -var_dump($email); +var_dump($story); echo str_repeat(PHP_EOL, 5); diff --git a/src/Concerns/FakesInputOutput.php b/src/Concerns/FakesInputOutput.php index e136db1de8871426bbd008d57badd3dfd1f46925..5bbf53fa5db037d58936970ea92319cd3389fd3f 100644 --- a/src/Concerns/FakesInputOutput.php +++ b/src/Concerns/FakesInputOutput.php @@ -35,7 +35,7 @@ trait FakesInputOutput static::$terminal = $mock; - self::setOutput(new BufferedConsoleOutput()); + self::setOutput(new BufferedConsoleOutput); } /** diff --git a/src/Concerns/Termwind.php b/src/Concerns/Termwind.php index 798348c67a3ce594936372c164bc53a449d15680..301776b1619cd13606922208c6901a4874fae785 100644 --- a/src/Concerns/Termwind.php +++ b/src/Concerns/Termwind.php @@ -11,7 +11,7 @@ trait Termwind { protected function termwind(string $html) { - renderUsing($output = new BufferedConsoleOutput()); + renderUsing($output = new BufferedConsoleOutput); render($html); diff --git a/src/ConfirmPrompt.php b/src/ConfirmPrompt.php index 23b8a97f5bcea1fb7e7615331ecb5b79fb34f0a9..3abccf07c39f3dd876ee70353c2b6e9cdac6863a 100644 --- a/src/ConfirmPrompt.php +++ b/src/ConfirmPrompt.php @@ -2,6 +2,8 @@ namespace Laravel\Prompts; +use Closure; + class ConfirmPrompt extends Prompt { /** @@ -20,6 +22,7 @@ class ConfirmPrompt extends Prompt public bool|string $required = false, public mixed $validate = null, public string $hint = '', + public ?Closure $transform = null, ) { $this->confirmed = $default; diff --git a/src/FormBuilder.php b/src/FormBuilder.php index 621c19b86ca8e441f885e1398368a19ecff1848c..4e5bd5d2ef6b720960319c4c79433769c1c30832 100644 --- a/src/FormBuilder.php +++ b/src/FormBuilder.php @@ -78,7 +78,7 @@ class FormBuilder /** * Prompt the user for text input. */ - public function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null): self + public function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(text(...), get_defined_vars()); } @@ -86,7 +86,7 @@ class FormBuilder /** * Prompt the user for multiline text input. */ - public function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5, ?string $name = null): self + public function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5, ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(textarea(...), get_defined_vars()); } @@ -94,7 +94,7 @@ class FormBuilder /** * Prompt the user for input, hiding the value. */ - public function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null): self + public function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(password(...), get_defined_vars()); } @@ -105,7 +105,7 @@ class FormBuilder * @param array<int|string, string>|Collection<int|string, string> $options * @param true|string $required */ - public function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null): self + public function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(select(...), get_defined_vars()); } @@ -116,7 +116,7 @@ class FormBuilder * @param array<int|string, string>|Collection<int|string, string> $options * @param array<int|string>|Collection<int, int|string> $default */ - public 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.', ?string $name = null): self + public 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.', ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(multiselect(...), get_defined_vars()); } @@ -124,7 +124,7 @@ class FormBuilder /** * Prompt the user to confirm an action. */ - public function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null): self + public function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(confirm(...), get_defined_vars()); } @@ -142,7 +142,7 @@ class FormBuilder * * @param array<string>|Collection<int, string>|Closure(string): array<string> $options */ - public function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null): self + public function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(suggest(...), get_defined_vars()); } @@ -153,7 +153,7 @@ class FormBuilder * @param Closure(string): array<int|string, string> $options * @param true|string $required */ - public function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null): self + public function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(search(...), get_defined_vars()); } @@ -163,7 +163,7 @@ class FormBuilder * * @param Closure(string): array<int|string, string> $options */ - public function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null): self + public function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null): self { return $this->runPrompt(multisearch(...), get_defined_vars()); } diff --git a/src/MultiSearchPrompt.php b/src/MultiSearchPrompt.php index 5aac82b567bdec649d4e464c0754d29b8bdec1ae..083f56b9d01ae6246026bc78e7680bacb21dfd43 100644 --- a/src/MultiSearchPrompt.php +++ b/src/MultiSearchPrompt.php @@ -42,6 +42,7 @@ class MultiSearchPrompt extends Prompt public bool|string $required = false, public mixed $validate = null, public string $hint = '', + public ?Closure $transform = null, ) { $this->trackTypedValue(submit: false, ignore: fn ($key) => Key::oneOf([Key::SPACE, Key::HOME, Key::END, Key::CTRL_A, Key::CTRL_E], $key) && $this->highlighted !== null); diff --git a/src/MultiSelectPrompt.php b/src/MultiSelectPrompt.php index 2dee528568bf97bdcfe430437eeb1aa865b13a19..c28bedf8b9571cf2d126429f7b7db35b73d46801 100644 --- a/src/MultiSelectPrompt.php +++ b/src/MultiSelectPrompt.php @@ -2,6 +2,7 @@ namespace Laravel\Prompts; +use Closure; use Illuminate\Support\Collection; class MultiSelectPrompt extends Prompt @@ -43,6 +44,7 @@ class MultiSelectPrompt extends Prompt public bool|string $required = false, public mixed $validate = null, public string $hint = '', + public ?Closure $transform = null, ) { $this->options = $options instanceof Collection ? $options->all() : $options; $this->default = $default instanceof Collection ? $default->all() : $default; diff --git a/src/PasswordPrompt.php b/src/PasswordPrompt.php index 31802c1e96fcc930ffa86069d58ec6c05fe9deba..41b755a69bd7c14351a54a0dc42694ccfbf64253 100644 --- a/src/PasswordPrompt.php +++ b/src/PasswordPrompt.php @@ -2,6 +2,8 @@ namespace Laravel\Prompts; +use Closure; + class PasswordPrompt extends Prompt { use Concerns\TypedValue; @@ -15,6 +17,7 @@ class PasswordPrompt extends Prompt public bool|string $required = false, public mixed $validate = null, public string $hint = '', + public ?Closure $transform = null, ) { $this->trackTypedValue(); } diff --git a/src/Prompt.php b/src/Prompt.php index 1d0709c9351397f5e0dc31df0d2de89360ce3074..560bc154f39e2f2dee8d9e22f03608dfc91b1211 100644 --- a/src/Prompt.php +++ b/src/Prompt.php @@ -50,6 +50,11 @@ abstract class Prompt */ public bool|string $required; + /** + * The transformation callback. + */ + public ?Closure $transform = null; + /** * The validator callback or rules. */ @@ -137,10 +142,10 @@ abstract class Prompt } if ($key === Key::CTRL_U && self::$revertUsing) { - throw new FormRevertedException(); + throw new FormRevertedException; } - return $this->value(); + return $this->transformedValue(); } } } finally { @@ -187,7 +192,7 @@ abstract class Prompt */ protected static function output(): OutputInterface { - return self::$output ??= new ConsoleOutput(); + return self::$output ??= new ConsoleOutput; } /** @@ -207,7 +212,7 @@ abstract class Prompt */ public static function terminal(): Terminal { - return static::$terminal ??= new Terminal(); + return static::$terminal ??= new Terminal; } /** @@ -277,7 +282,7 @@ abstract class Prompt */ protected function submit(): void { - $this->validate($this->value()); + $this->validate($this->transformedValue()); if ($this->state !== 'error') { $this->state = 'submit'; @@ -322,12 +327,32 @@ abstract class Prompt } if ($this->validated) { - $this->validate($this->value()); + $this->validate($this->transformedValue()); } return true; } + /** + * Transform the input. + */ + private function transform(mixed $value): mixed + { + if (is_null($this->transform)) { + return $value; + } + + return call_user_func($this->transform, $value); + } + + /** + * Get the transformed value of the prompt. + */ + protected function transformedValue(): mixed + { + return $this->transform($this->value()); + } + /** * Validate the input. */ diff --git a/src/SearchPrompt.php b/src/SearchPrompt.php index b9b820cefab68305cac52fab7d50027eb3c878a3..259b4299e1fb65f35626e7af8c10cb56b6f9bfd6 100644 --- a/src/SearchPrompt.php +++ b/src/SearchPrompt.php @@ -31,6 +31,7 @@ class SearchPrompt extends Prompt public mixed $validate = null, public string $hint = '', public bool|string $required = true, + public ?Closure $transform = null, ) { if ($this->required === false) { throw new InvalidArgumentException('Argument [required] must be true or a string.'); diff --git a/src/SelectPrompt.php b/src/SelectPrompt.php index 081f09c7b0e43f4b29fe06810dc1bc17a5fc0bf8..8d48a73007236b4d309c52466fc4a77c1425ded0 100644 --- a/src/SelectPrompt.php +++ b/src/SelectPrompt.php @@ -2,6 +2,7 @@ namespace Laravel\Prompts; +use Closure; use Illuminate\Support\Collection; use InvalidArgumentException; @@ -29,6 +30,7 @@ class SelectPrompt extends Prompt public mixed $validate = null, public string $hint = '', public bool|string $required = true, + public ?Closure $transform = null, ) { if ($this->required === false) { throw new InvalidArgumentException('Argument [required] must be true or a string.'); diff --git a/src/SuggestPrompt.php b/src/SuggestPrompt.php index dd8d2553cc6aecd6c17b3cc3204ab9d2dd512247..73efbdca1a5eadcf7d6bf31a6e5f069d1d7df256 100644 --- a/src/SuggestPrompt.php +++ b/src/SuggestPrompt.php @@ -39,6 +39,7 @@ class SuggestPrompt extends Prompt public bool|string $required = false, public mixed $validate = null, public string $hint = '', + public ?Closure $transform = null, ) { $this->options = $options instanceof Collection ? $options->all() : $options; diff --git a/src/Terminal.php b/src/Terminal.php index b91fea89fa8582a562c9240303d552a39827fd77..631b2a5a0a0805b2456b03d8a7c92a65b59a81e8 100644 --- a/src/Terminal.php +++ b/src/Terminal.php @@ -23,7 +23,7 @@ class Terminal */ public function __construct() { - $this->terminal = new SymfonyTerminal(); + $this->terminal = new SymfonyTerminal; } /** diff --git a/src/TextPrompt.php b/src/TextPrompt.php index 74a41a5e023373707343824847d1d5f1566fa380..db63f81bf7892d75d2a1517277e23b5006b2da9e 100644 --- a/src/TextPrompt.php +++ b/src/TextPrompt.php @@ -2,6 +2,8 @@ namespace Laravel\Prompts; +use Closure; + class TextPrompt extends Prompt { use Concerns\TypedValue; @@ -16,6 +18,7 @@ class TextPrompt extends Prompt public bool|string $required = false, public mixed $validate = null, public string $hint = '', + public ?Closure $transform = null, ) { $this->trackTypedValue($default); } diff --git a/src/TextareaPrompt.php b/src/TextareaPrompt.php index 859469a4862cfbe919d9d09d32b7f0a9fe43e8c4..e5a336668df77f5684acf9ef0caa7e9180cf7af8 100644 --- a/src/TextareaPrompt.php +++ b/src/TextareaPrompt.php @@ -2,6 +2,8 @@ namespace Laravel\Prompts; +use Closure; + class TextareaPrompt extends Prompt { use Concerns\Scrolling; @@ -24,6 +26,7 @@ class TextareaPrompt extends Prompt public mixed $validate = null, public string $hint = '', int $rows = 5, + public ?Closure $transform = null, ) { $this->scroll = $rows; diff --git a/src/Themes/Default/TableRenderer.php b/src/Themes/Default/TableRenderer.php index 185f450017abe7ee9816b1ec59a4fcafabf2841f..c2d17bb94a92d224624a7fe26cdffc562de581cf 100644 --- a/src/Themes/Default/TableRenderer.php +++ b/src/Themes/Default/TableRenderer.php @@ -14,7 +14,7 @@ class TableRenderer extends Renderer */ public function __invoke(Table $table): string { - $tableStyle = (new TableStyle()) + $tableStyle = (new TableStyle) ->setHorizontalBorderChars('─') ->setVerticalBorderChars('│', '│') ->setCellHeaderFormat($this->dim('<fg=default>%s</>')) @@ -26,7 +26,7 @@ class TableRenderer extends Renderer $tableStyle->setCrossingChars('┼', '<fg=gray>┌', '┬', '┐', '┤', '┘</>', '┴', '└', '├'); } - $buffered = new BufferedConsoleOutput(); + $buffered = new BufferedConsoleOutput; (new SymfonyTable($buffered)) ->setHeaders($table->headers) diff --git a/src/helpers.php b/src/helpers.php index f49a9912e56d9ad1e23eb5d4def45b7149c3ca06..65545e037c024870264c5f20b6c1dbae12a20a06 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -9,7 +9,7 @@ if (! function_exists('\Laravel\Prompts\text')) { /** * Prompt the user for text input. */ - function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = ''): string + function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?Closure $transform = null): string { return (new TextPrompt(...func_get_args()))->prompt(); } @@ -19,9 +19,9 @@ if (! function_exists('\Laravel\Prompts\textarea')) { /** * Prompt the user for multiline text input. */ - function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5): string + function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', int $rows = 5, ?Closure $transform = null): string { - return (new TextareaPrompt($label, $placeholder, $default, $required, $validate, $hint, $rows))->prompt(); + return (new TextareaPrompt(...func_get_args()))->prompt(); } } @@ -29,7 +29,7 @@ if (! function_exists('\Laravel\Prompts\password')) { /** * Prompt the user for input, hiding the value. */ - function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = ''): string + function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?Closure $transform = null): string { return (new PasswordPrompt(...func_get_args()))->prompt(); } @@ -42,7 +42,7 @@ if (! function_exists('\Laravel\Prompts\select')) { * @param array<int|string, string>|Collection<int|string, string> $options * @param true|string $required */ - function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true): int|string + function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?Closure $transform = null): int|string { return (new SelectPrompt(...func_get_args()))->prompt(); } @@ -56,7 +56,7 @@ if (! function_exists('\Laravel\Prompts\multiselect')) { * @param array<int|string>|Collection<int, int|string> $default * @return array<int|string> */ - 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, string $hint = 'Use the space bar to select options.', ?Closure $transform = null): array { return (new MultiSelectPrompt(...func_get_args()))->prompt(); } @@ -66,7 +66,7 @@ if (! function_exists('\Laravel\Prompts\confirm')) { /** * Prompt the user to confirm an action. */ - function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = ''): bool + function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?Closure $transform = null): bool { return (new ConfirmPrompt(...func_get_args()))->prompt(); } @@ -88,7 +88,7 @@ if (! function_exists('\Laravel\Prompts\suggest')) { * * @param array<string>|Collection<int, string>|Closure(string): array<string> $options */ - function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = ''): string + function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?Closure $transform = null): string { return (new SuggestPrompt(...func_get_args()))->prompt(); } @@ -101,7 +101,7 @@ if (! function_exists('\Laravel\Prompts\search')) { * @param Closure(string): array<int|string, string> $options * @param true|string $required */ - function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true): int|string + function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?Closure $transform = null): int|string { return (new SearchPrompt(...func_get_args()))->prompt(); } @@ -114,7 +114,7 @@ if (! function_exists('\Laravel\Prompts\multisearch')) { * @param Closure(string): array<int|string, string> $options * @return array<int|string> */ - function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.'): array + function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?Closure $transform = null): array { return (new MultiSearchPrompt(...func_get_args()))->prompt(); } @@ -244,6 +244,6 @@ if (! function_exists('\Laravel\Prompts\progress')) { if (! function_exists('\Laravel\Prompts\form')) { function form(): FormBuilder { - return new FormBuilder(); + return new FormBuilder; } } diff --git a/tests/Feature/ConfirmPromptTest.php b/tests/Feature/ConfirmPromptTest.php index 79d703fd3bdc72ca0772e5ac2d8fd1ef860d6fdc..4d61fff38dd999c9b126a7458730d4f334b90759 100644 --- a/tests/Feature/ConfirmPromptTest.php +++ b/tests/Feature/ConfirmPromptTest.php @@ -65,6 +65,17 @@ it('allows the labels to be changed', function () { Prompt::assertOutputContains('No, gracias'); }); +it('transforms values', function () { + Prompt::fake([Key::ENTER]); + + $result = confirm( + label: 'Are you sure?', + transform: fn ($value) => ! $value, + ); + + expect($result)->toBeFalse(); +}); + it('validates', function () { Prompt::fake([Key::ENTER, 'y', Key::ENTER]); diff --git a/tests/Feature/MultiSearchPromptTest.php b/tests/Feature/MultiSearchPromptTest.php index 5b7a9b313f0ac14203c2b0d14a989276d30cd1c5..b5ce5dc3785da1562c33e9edb974e70a6572b94c 100644 --- a/tests/Feature/MultiSearchPromptTest.php +++ b/tests/Feature/MultiSearchPromptTest.php @@ -252,6 +252,22 @@ it('supports no default results', function ($options, $expected) { ], ]); +it('transforms values', function () { + Prompt::fake([Key::DOWN, Key::CTRL_A, Key::ENTER]); + + $result = multisearch( + label: 'What are your favorite colors?', + options: fn () => [ + 'red' => 'Red', + 'green' => 'Green', + 'blue' => 'Blue', + ], + transform: fn ($value) => array_map('strtoupper', $value), + ); + + expect($result)->toBe(['RED', 'GREEN', 'BLUE']); +}); + it('validates', function () { Prompt::fake(['a', Key::DOWN, Key::SPACE, Key::ENTER, Key::DOWN, Key::SPACE, Key::ENTER]); diff --git a/tests/Feature/MultiSelectPromptTest.php b/tests/Feature/MultiSelectPromptTest.php index df834a3f082958a22458ad708bf2aa60ed9877f5..1aa49e10547d17fd289828aeb28b6918dac7b5a1 100644 --- a/tests/Feature/MultiSelectPromptTest.php +++ b/tests/Feature/MultiSelectPromptTest.php @@ -104,6 +104,22 @@ it('accepts collections', function () { expect($result)->toBe(['Green']); }); +it('transforms values', function () { + Prompt::fake([Key::DOWN, Key::SPACE, Key::DOWN, Key::SPACE, Key::ENTER]); + + $result = multiselect( + label: 'What are your favorite colors?', + options: [ + 'red' => 'Red', + 'green' => 'Green', + 'blue' => 'Blue', + ], + transform: fn ($value) => array_map('strtoupper', $value), + ); + + expect($result)->toBe(['GREEN', 'BLUE']); +}); + it('validates', function () { Prompt::fake([Key::ENTER, Key::SPACE, Key::ENTER]); diff --git a/tests/Feature/PasswordPromptTest.php b/tests/Feature/PasswordPromptTest.php index 795e9e779a3361754154ba12e0fb6798cb8d2fb7..277149c3f4542aa480c0dbc61687a266fdfe8123 100644 --- a/tests/Feature/PasswordPromptTest.php +++ b/tests/Feature/PasswordPromptTest.php @@ -15,6 +15,19 @@ it('returns the input', function () { expect($result)->toBe('pass'); }); +it('transforms values', function () { + Prompt::fake(['p', 'a', 's', 's', 'w', 'o', 'r', 'd', Key::ENTER]); + + $dontUseInProduction = md5('password'); + + $result = password( + label: 'What is the password?', + transform: fn ($value) => md5($value) + ); + + expect($result)->toBe($dontUseInProduction); +}); + it('validates', function () { Prompt::fake(['p', 'a', 's', Key::ENTER, 's', Key::ENTER]); diff --git a/tests/Feature/SearchPromptTest.php b/tests/Feature/SearchPromptTest.php index cf196a9c8ab25872f7e3d56ac5abdf156fcc5791..0a060cacdc6a1c1a1fed64ea0f4799095c9be558 100644 --- a/tests/Feature/SearchPromptTest.php +++ b/tests/Feature/SearchPromptTest.php @@ -97,6 +97,25 @@ it('returns the key when an associative array is passed', function () { expect($result)->toBe(3); }); +it('transforms values', function () { + Prompt::fake(['u', 'e', Key::DOWN, Key::ENTER]); + + $result = search( + label: 'What is your favorite color?', + options: fn (string $value) => array_filter( + [ + 'red' => 'Red', + 'green' => 'Green', + 'blue' => 'Blue', + ], + fn ($option) => str_contains(strtolower($option), $value), + ), + transform: fn ($value) => strtoupper($value), + ); + + expect($result)->toBe('BLUE'); +}); + it('validates', function () { Prompt::fake([Key::DOWN, Key::ENTER, Key::DOWN, Key::ENTER]); diff --git a/tests/Feature/SelectPromptTest.php b/tests/Feature/SelectPromptTest.php index 32b4deaabe103bd71d009a1705711725adabd60a..8ea4689dee315992b322e4d48e745648a1508ba0 100644 --- a/tests/Feature/SelectPromptTest.php +++ b/tests/Feature/SelectPromptTest.php @@ -99,6 +99,22 @@ it('accepts default values when the options are keys with labels', function () { expect($result)->toBe('green'); }); +it('transforms values', function () { + Prompt::fake([Key::DOWN, Key::ENTER]); + + $result = select( + label: 'What is your favorite color?', + options: [ + 'Red', + 'Green', + 'Blue', + ], + transform: fn ($value) => strtolower($value), + ); + + expect($result)->toBe('green'); +}); + it('validates', function () { Prompt::fake([Key::ENTER, Key::DOWN, Key::ENTER]); diff --git a/tests/Feature/SuggestPromptTest.php b/tests/Feature/SuggestPromptTest.php index dd23d9c7cbaa2df79095a4a1d5c730be9b3986b4..384a7a6f62472024fcd3a102752dab09b475a87c 100644 --- a/tests/Feature/SuggestPromptTest.php +++ b/tests/Feature/SuggestPromptTest.php @@ -118,6 +118,18 @@ it('accepts a callback returning a collection', function () { expect($result)->toBe('Blue'); }); +it('transforms values', function () { + Prompt::fake([Key::SPACE, 'J', 'e', 's', 's', Key::TAB, Key::ENTER]); + + $result = suggest( + label: 'What is your name?', + options: ['Jess'], + transform: fn ($value) => trim($value), + ); + + expect($result)->toBe('Jess'); +}); + it('validates', function () { Prompt::fake([Key::ENTER, 'X', Key::ENTER]); diff --git a/tests/Feature/TextPromptTest.php b/tests/Feature/TextPromptTest.php index 541628adc8d9550b2b75a7708023f9dbdec471e0..f11ac538bf90371967bb07a772362657d58ae08b 100644 --- a/tests/Feature/TextPromptTest.php +++ b/tests/Feature/TextPromptTest.php @@ -30,6 +30,17 @@ it('accepts a default value', function () { expect($result)->toBe('Jess'); }); +it('transforms values', function () { + Prompt::fake([Key::SPACE, 'J', 'e', 's', 's', Key::TAB, Key::ENTER]); + + $result = text( + label: 'What is your name?', + transform: fn ($value) => trim($value), + ); + + expect($result)->toBe('Jess'); +}); + it('validates', function () { Prompt::fake(['J', 'e', 's', Key::ENTER, 's', Key::ENTER]); diff --git a/tests/Feature/TextareaPromptTest.php b/tests/Feature/TextareaPromptTest.php index 0720919542c90d55f772dc73635df7ef78830d6d..f5e21b17c95d129a62cd5b3b25b31cceb2671b50 100644 --- a/tests/Feature/TextareaPromptTest.php +++ b/tests/Feature/TextareaPromptTest.php @@ -26,6 +26,17 @@ it('accepts a default value', function () { expect($result)->toBe("Jess\nJoe"); }); +it('transforms values', function () { + Prompt::fake([Key::SPACE, 'J', 'e', 's', 's', Key::SPACE, Key::CTRL_D]); + + $result = textarea( + label: 'What is your name?', + transform: fn ($value) => trim($value), + ); + + expect($result)->toBe('Jess'); +}); + it('validates', function () { Prompt::fake(['J', 'e', 's', Key::CTRL_D, 's', Key::CTRL_D]);