Skip to content

Commit 7c64c7c

Browse files
authored
feat(console): improve rescuing enum console parameters (#809)
1 parent 5e3d99e commit 7c64c7c

File tree

5 files changed

+91
-3
lines changed

5 files changed

+91
-3
lines changed

src/Tempest/Console/src/Middleware/InvalidCommandMiddleware.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Tempest\Console\Middleware;
66

7+
use BackedEnum;
78
use Tempest\Console\Actions\ExecuteConsoleCommand;
89
use Tempest\Console\Console;
910
use Tempest\Console\ConsoleMiddleware;
@@ -15,6 +16,7 @@
1516
use Tempest\Console\Input\ConsoleInputArgument;
1617
use function Tempest\Support\str;
1718
use Tempest\Validation\Rules\Boolean;
19+
use Tempest\Validation\Rules\Enum;
1820
use Tempest\Validation\Rules\NotEmpty;
1921
use Tempest\Validation\Rules\Numeric;
2022

@@ -44,17 +46,24 @@ private function retry(Invocation $invocation, InvalidCommandException $exceptio
4446

4547
/** @var ConsoleArgumentDefinition $argument */
4648
foreach ($exception->invalidArguments as $argument) {
49+
$isEnum = is_a($argument->type, BackedEnum::class, allow_string: true);
4750
$value = $this->console->ask(
4851
question: str($argument->name)->snake(' ')->upperFirst()->toString(),
4952
default: (string) $argument->default,
5053
hint: $argument->help ?? $argument->description,
51-
validation: [
54+
options: $isEnum
55+
? $argument->type
56+
: null,
57+
validation: array_filter([
58+
$isEnum
59+
? new Enum($argument->type)
60+
: new NotEmpty(),
5261
match ($argument->type) {
5362
'bool' => new Boolean(),
5463
'int' => new Numeric(),
55-
default => new NotEmpty(),
64+
default => null,
5665
},
57-
]
66+
])
5867
);
5968

6069
$invocation->argumentBag->add(new ConsoleInputArgument(
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Console\Fixtures;
6+
7+
use Tempest\Console\Console;
8+
use Tempest\Console\ConsoleCommand;
9+
10+
final readonly class IntEnumCommand
11+
{
12+
public function __construct(private Console $console)
13+
{
14+
}
15+
16+
#[ConsoleCommand('int-enum-from-one-command')]
17+
public function __invoke(TestIntEnumFromOne $enum): void
18+
{
19+
$this->console->writeln($enum->name);
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Console\Fixtures;
6+
7+
use Tempest\Console\Console;
8+
use Tempest\Console\ConsoleCommand;
9+
10+
final readonly class StringEnumCommand
11+
{
12+
public function __construct(private Console $console)
13+
{
14+
}
15+
16+
#[ConsoleCommand('string-enum-command')]
17+
public function __invoke(TestStringEnum $enum): void
18+
{
19+
$this->console->writeln($enum->value);
20+
}
21+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Console\Fixtures;
6+
7+
// This doesn't start from zero
8+
enum TestIntEnumFromOne: int
9+
{
10+
case A = 1;
11+
case B = 2;
12+
case C = 3;
13+
}

tests/Integration/Console/Middleware/InvalidCommandMiddlewareTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
namespace Tests\Tempest\Integration\Console\Middleware;
66

77
use Tests\Tempest\Integration\Console\Fixtures\ComplexCommand;
8+
use Tests\Tempest\Integration\Console\Fixtures\IntEnumCommand;
9+
use Tests\Tempest\Integration\Console\Fixtures\StringEnumCommand;
810
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
911

1012
/**
@@ -22,4 +24,26 @@ public function test_provide_missing_input(): void
2224
->submit('c')
2325
->assertContains('abc');
2426
}
27+
28+
public function test_with_string_enum(): void
29+
{
30+
$this->console
31+
->call(StringEnumCommand::class)
32+
->assertContains('A')
33+
->assertContains('B')
34+
->assertContains('C')
35+
->input(1)
36+
->assertContains('b');
37+
}
38+
39+
public function test_with_int_enum(): void
40+
{
41+
$this->console
42+
->call(IntEnumCommand::class)
43+
->assertContains('A')
44+
->assertContains('B')
45+
->assertContains('C')
46+
->input(1)
47+
->assertContains('B');
48+
}
2549
}

0 commit comments

Comments
 (0)