Skip to content

Commit

Permalink
Add non-interactive mode
Browse files Browse the repository at this point in the history
  • Loading branch information
jessarcher committed Sep 18, 2023
1 parent 61f61cd commit 158eb3f
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/Concerns/Interactivity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Laravel\Prompts\Concerns;

use Laravel\Prompts\Exceptions\NonInteractiveValidationException;

trait Interactivity
{
/**
* Whether to render the prompt interactively.
*/
protected static bool $interactive;

/**
* Set interactive mode.
*/
public static function interactive(bool $interactive = true): void
{
static::$interactive = $interactive;
}

/**
* Return the default value if it passes validation.
*/
protected function default(): mixed
{
$default = $this->value();

$this->validate($default);

if ($this->state === 'error') {
throw new NonInteractiveValidationException($this->error);
}

return $default;
}
}
10 changes: 10 additions & 0 deletions src/Exceptions/NonInteractiveValidationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Laravel\Prompts\Exceptions;

use RuntimeException;

class NonInteractiveValidationException extends RuntimeException
{
//
}
7 changes: 7 additions & 0 deletions src/Prompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ abstract class Prompt
use Concerns\Events;
use Concerns\FakesInputOutput;
use Concerns\Fallback;
use Concerns\Interactivity;
use Concerns\Themes;

/**
Expand Down Expand Up @@ -73,6 +74,12 @@ abstract public function value(): mixed;
*/
public function prompt(): mixed
{
static::$interactive ??= stream_isatty(STDIN);

if (! static::$interactive) {
return $this->default();
}

$this->capturePreviousNewLines();

if (static::shouldFallback()) {
Expand Down
9 changes: 9 additions & 0 deletions src/SearchPrompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Laravel\Prompts;

use Closure;
use Laravel\Prompts\Exceptions\NonInteractiveValidationException;

class SearchPrompt extends Prompt
{
Expand Down Expand Up @@ -178,4 +179,12 @@ public function label(): ?string
{
return $this->matches[array_keys($this->matches)[$this->highlighted]] ?? null;
}

/**
* Fail when non-interactive.
*/
protected function default(): mixed
{
throw new NonInteractiveValidationException('Required.');
}
}
13 changes: 13 additions & 0 deletions src/SelectPrompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Closure;
use Illuminate\Support\Collection;
use Laravel\Prompts\Exceptions\NonInteractiveValidationException;

class SelectPrompt extends Prompt
{
Expand Down Expand Up @@ -138,4 +139,16 @@ protected function highlightNext(): void
$this->firstVisible = 0;
}
}

/**
* Return the default value if it passes validation.
*/
protected function default(): mixed
{
if ($this->default === null) {
throw new NonInteractiveValidationException('Required.');
}

return parent::default();
}
}
19 changes: 19 additions & 0 deletions tests/Feature/ConfirmPromptTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Laravel\Prompts\ConfirmPrompt;
use Laravel\Prompts\Exceptions\NonInteractiveValidationException;
use Laravel\Prompts\Key;
use Laravel\Prompts\Prompt;

Expand Down Expand Up @@ -99,3 +100,21 @@

expect($result)->toBeFalse();
});

it('returns the default value when non-interactive', function () {
Prompt::interactive(false);

$result = confirm('Would you like to continue?', false);

expect($result)->toBeFalse();
});

it('validates the default value when non-interactive', function () {
Prompt::interactive(false);

confirm(
'Would you like to continue?',
default: false,
required: true,
);
})->throws(NonInteractiveValidationException::class, 'Required.');
35 changes: 35 additions & 0 deletions tests/Feature/MultiselectPromptTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use Laravel\Prompts\Exceptions\NonInteractiveValidationException;
use Laravel\Prompts\Key;
use Laravel\Prompts\MultiSelectPrompt;
use Laravel\Prompts\Prompt;
Expand Down Expand Up @@ -153,3 +154,37 @@

expect($result)->toBe(['green', 'blue']);
});

it('returns an empty array when non-interactive', function () {
Prompt::interactive(false);

$result = multiselect('What is your favorite color?', [
'Red',
'Green',
'Blue',
]);

expect($result)->toBe([]);
});

it('returns the default value when non-interactive', function () {
Prompt::interactive(false);

$result = multiselect('What is your favorite color?', [
'Red',
'Green',
'Blue',
], default: ['Green']);

expect($result)->toBe(['Green']);
});

it('validates the default value when non-interactive', function () {
Prompt::interactive(false);

multiselect('What is your favorite color?', [
'Red',
'Green',
'Blue',
], required: true);
})->throws(NonInteractiveValidationException::class, 'Required.');
15 changes: 15 additions & 0 deletions tests/Feature/PasswordPromptTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use Laravel\Prompts\Exceptions\NonInteractiveValidationException;
use Laravel\Prompts\Key;
use Laravel\Prompts\PasswordPrompt;
use Laravel\Prompts\Prompt;
Expand Down Expand Up @@ -64,3 +65,17 @@

expect($result)->toBe('result');
});

it('returns an empty string when non-interactive', function () {
Prompt::interactive(false);

$result = password('What is the password?');

expect($result)->toBe('');
});

it('fails validation when non-interactive', function () {
Prompt::interactive(false);

password('What is the password?', required: true);
})->throws(NonInteractiveValidationException::class, 'Required.');
7 changes: 7 additions & 0 deletions tests/Feature/SearchPromptTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use Laravel\Prompts\Exceptions\NonInteractiveValidationException;
use Laravel\Prompts\Key;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\SearchPrompt;
Expand Down Expand Up @@ -116,3 +117,9 @@

expect($result)->toBe('blue');
});

it('fails when when non-interactive', function () {
Prompt::interactive(false);

search('What is your favorite color?', fn () => []);
})->throws(NonInteractiveValidationException::class, 'Required.');
39 changes: 39 additions & 0 deletions tests/Feature/SelectPromptTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use Laravel\Prompts\Exceptions\NonInteractiveValidationException;
use Laravel\Prompts\Key;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\SelectPrompt;
Expand Down Expand Up @@ -224,3 +225,41 @@

expect($result)->toBe('Green');
});

it('fails when there is no default in non-interactive mode', function () {
Prompt::interactive(false);

select('What is your favorite color?', [
'Red',
'Green',
'Blue',
]);
})->throws(NonInteractiveValidationException::class, 'Required.');

it('returns the default value when non-interactive', function () {
Prompt::interactive(false);

$result = select('What is your favorite color?', [
'Red',
'Green',
'Blue',
], default: 'Green');

expect($result)->toBe('Green');
});

it('validates the default value when non-interactive', function () {
Prompt::interactive(false);

select(
label: 'What is your favorite color?',
options: [
'None',
'Red',
'Green',
'Blue',
],
default: 'None',
validate: fn ($value) => $value === 'None' ? 'Required.' : null,
);
})->throws(NonInteractiveValidationException::class, 'Required.');
35 changes: 35 additions & 0 deletions tests/Feature/SuggestPromptTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use Laravel\Prompts\Exceptions\NonInteractiveValidationException;
use Laravel\Prompts\Key;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\SuggestPrompt;
Expand Down Expand Up @@ -117,3 +118,37 @@

expect($result)->toBe('Black');
});

it('returns an empty string when non-interactive', function () {
Prompt::interactive(false);

$result = suggest('What is your favorite color?', [
'Red',
'Green',
'Blue',
]);

expect($result)->toBe('');
});

it('returns the default value when non-interactive', function () {
Prompt::interactive(false);

$result = suggest('What is your favorite color?', [
'Red',
'Green',
'Blue',
], default: 'Yellow');

expect($result)->toBe('Yellow');
});

it('validates the default value when non-interactive', function () {
Prompt::interactive(false);

suggest('What is your favorite color?', [
'Red',
'Green',
'Blue',
], required: true);
})->throws(NonInteractiveValidationException::class, 'Required.');
23 changes: 23 additions & 0 deletions tests/Feature/TextPromptTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use Laravel\Prompts\Exceptions\NonInteractiveValidationException;
use Laravel\Prompts\Key;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\TextPrompt;
Expand Down Expand Up @@ -91,3 +92,25 @@

expect($result)->toBe('Jess');
});

it('returns an empty string when non-interactive', function () {
Prompt::interactive(false);

$result = text('What is your name?');

expect($result)->toBe('');
});

it('returns the default value when non-interactive', function () {
Prompt::interactive(false);

$result = text('What is your name?', default: 'Taylor');

expect($result)->toBe('Taylor');
});

it('validates the default value when non-interactive', function () {
Prompt::interactive(false);

text('What is your name?', required: true);
})->throws(NonInteractiveValidationException::class, 'Required.');

0 comments on commit 158eb3f

Please sign in to comment.