8000 [Console] Remove restriction for choices to be strings by LordZardeck · Pull Request #34790 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Console] Remove restriction for choices to be strings #34790

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Symfony/Component/Console/Question/ChoiceQuestion.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ private function getDefaultValidator(): callable
throw new InvalidArgumentException(sprintf($errorMessage, $value));
}

$multiselectChoices[] = (string) $result;
// For associative choices, consistently return the key as string:
$multiselectChoices[] = $isAssoc ? (string) $result : $result;
}

if ($multiselect) {
Expand Down
35 changes: 0 additions & 35 deletions src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -570,41 +570,6 @@ public function specialCharacterInMultipleChoice()
];
}

/**
* @dataProvider mixedKeysChoiceListAnswerProvider
*/
public function testChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue)
{
$possibleChoices = [
'0' => 'No environment',
'1' => 'My environment 1',
'env_2' => 'My environment 2',
3 => 'My environment 3',
];

$dialog = new QuestionHelper();
$helperSet = new HelperSet([new FormatterHelper()]);
$dialog->setHelperSet($helperSet);

$question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
$question->setMaxAttempts(1);
$answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question);

$this->assertSame($expectedValue, $answer);
}

public function mixedKeysChoiceListAnswerProvider()
{
return [
['0', '0'],
['No environment', '0'],
['1', '1'],
['env_2', 'env_2'],
[3, '3'],
['My environment 1', '1'],
];
}

/**
* @dataProvider answerProvider
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ public function selectUseCases()
['First response', 'Second response'],
'When passed multiple answers on MultiSelect, the defaultValidator must return these answers as an array',
],
[
false,
[0],
'First response',
'When passed single answer using choice\'s key, the defaultValidator must return the choice value',
],
[
true,
['0, 2'],
['First response', 'Third response'],
'When passed multiple answers using choices\' key, the defaultValidator must return the choice values in an array',
],
];
}

Expand All @@ -77,4 +89,64 @@ public function testNonTrimmable()

$this->assertSame(['First response ', ' Second response'], $question->getValidator()('First response , Second response'));
}

/**
* @dataProvider selectAssociativeChoicesProvider
*/
public function testSelectAssociativeChoices($providedAnswer, $expectedValue)
{
$question = new ChoiceQuestion('A question', [
'0' => 'First choice',
'foo' => 'Foo',
'99' => 'N°99',
'string object' => new StringChoice('String Object'),
]);

$this->assertSame($expectedValue, $question->getValidator()($providedAnswer));
}

public function selectAssociativeChoicesProvider()
{
return [
'select "0" choice by key' => ['0', '0'],
'select "0" choice by value' => ['First choice', '0'],
'select by key' => ['foo', 'foo'],
'select by value' => ['Foo', 'foo'],
'select by key, with numeric key' => ['99', '99'],
'select by value, with numeric key' => ['N°99', '99'],
'select by key, with string object value' => ['string object', 'string object'],
'select by value, with string object value' => ['String Object', 'string object'],
];
}

public function testSelectWithNonStringChoices()
{
$question = new ChoiceQuestion('A question', [
$result1 = new StringChoice('foo'),
$result2 = new StringChoice('bar'),
$result3 = new StringChoice('baz'),
]);

$this->assertSame($result1, $question->getValidator()('foo'), 'answer can be selected by its string value');
$this->assertSame($result1, $question->getValidator()(0), 'answer can be selected by index');

$question->setMultiselect(true);

$this->assertSame([$result3, $result2], $question->getValidator()('baz, bar'));
}
}

class StringChoice
{
private $string;

public function __construct(string $string)
{
$this->string = $string;
}

public function __toString()
{
return $this->string;
}
}
0