[Console] Cast associative choices questions keys to string

to prevent inconsistency when choosing by key (getting a string as result) or by value (getting an int as result)
This commit is contained in:
Maxime Steinhausser 2020-08-31 16:36:30 +02:00
parent a0223088a0
commit d276cc9ca3
3 changed files with 45 additions and 37 deletions

View File

@ -169,7 +169,8 @@ class ChoiceQuestion extends Question
throw new InvalidArgumentException(sprintf($errorMessage, $value));
}
$multiselectChoices[] = $result;
// For associative choices, consistently return the key as string:
$multiselectChoices[] = $isAssoc ? (string) $result : $result;
}
if ($multiselect) {

View File

@ -570,41 +570,6 @@ class QuestionHelperTest extends AbstractQuestionHelperTest
];
}
/**
* @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
*/

View File

@ -59,6 +59,18 @@ class ChoiceQuestionTest extends TestCase
['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',
],
];
}
@ -78,6 +90,35 @@ class ChoiceQuestionTest extends TestCase
$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', [
@ -86,7 +127,8 @@ class ChoiceQuestionTest extends TestCase
$result3 = new StringChoice('baz'),
]);
$this->assertSame($result1, $question->getValidator()('foo'));
$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);