Skip to content

Commit

Permalink
Reworked the Input mock, added Choice questions with validation
Browse files Browse the repository at this point in the history
The Input mock previously didn't allow multiple questions. So i've
updated it to php://memory so it is still a stream, you can set answers
to multiple questions by line breaking them.
  • Loading branch information
Danzabar committed Nov 25, 2014
1 parent 59edc1b commit 6af4e5f
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 2 deletions.
17 changes: 15 additions & 2 deletions src/Input/InputMock.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ class InputMock implements InputInterface
*/
protected $input;

/**
* The input Stream
*
* @var string
*/
protected $inputStream;

/**
* Set up the input
*
Expand All @@ -28,7 +35,11 @@ class InputMock implements InputInterface
*/
public function __construct($str)
{
$this->input = $str;
$this->inputStream = fopen('php://memory', 'r+', false);

fputs($this->inputStream, $str);

rewind($this->inputStream);
}

/**
Expand All @@ -39,7 +50,9 @@ public function __construct($str)
*/
public function getInput()
{
return $this->input;
$this->input = fgets($this->inputStream);

return trim($this->input);
}


Expand Down
74 changes: 74 additions & 0 deletions src/Traits/Question.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
*/
Trait Question
{

/**
* The error message displayed when the user selects the wrong choices.
*
* @var string
*/
protected $wrongChoiceErrorMessage = 'The answer you selected is invalid.';

/**
* Asks a basic question and returns the response.
Expand All @@ -20,4 +27,71 @@ public function ask($question)
return $this->input->getInput();
}

/**
* Sets the error message that displays when a user picks the wrong answer
*
* @return void
* @author Dan Cox
*/
public function setChoiceError($error)
{
$this->wrongChoiceErrorMessage = $error;
}

/**
* The choice question, pick a single choice.
*
* @return String
* @author Dan Cox
*/
public function choice($question, $choices = Array())
{
$this->output->writeln($question);

$this->output->writeln(join(',', $choices));

$answer = $this->input->getInput();

$valid = $this->validateChoices(trim($answer), $choices);

if($valid)
{
return $answer;
}

$this->output->writeln($this->wrongChoiceErrorMessage);

return false;
}

/**
* Checks that the answer is present in the list of choices
*
* @return Boolean
* @author Dan Cox
*/
public function validateChoices($answer, $choices)
{
$answersArr = explode(',', $answer);

if(count($answersArr) == 1)
{
if(!in_array($answer, $choices))
{
return false;
}

} else
{
foreach($answersArr as $ans)
{
if(!in_array($ans, $choices))
{
return false;
}
}
}

return true;
}
}
38 changes: 38 additions & 0 deletions tests/Commands/FakeTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,43 @@ public function askAction()
$this->output->writeln($answer);
}

/**
* A double question task
*
* @return void
* @author Dan Cox
*/
public function advAskAction()
{
$prelim = $this->ask('Do you like questions?');

if($prelim == 'yes')
{
$answer = $this->ask('Great, so whats your favourite question?');

$this->output->writeln($answer);
}
}

/**
* Task that asks a choice question
*
* @return void
* @author Dan Cox
*/
public function choiceAction()
{
$choices = Array('one', 'two', 'three');

$answer = $this->choice('Select one of the following:', $choices);

if($answer)
{
$this->output->writeln("You have selected $answer");
}
}




} // END class TestCommand extends Command
28 changes: 28 additions & 0 deletions tests/Traits/QuestionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,32 @@ public function test_askQuestion()
$this->assertContains('answer', $this->CT->getOutput());
}

/**
* A bit more complicated testing a question that expects two sets of input.
*
* @return void
* @author Dan Cox
*/
public function test_advQuestion()
{
$this->CT->setInput("yes\nAnswer\n");
$this->CT->execute('Fake:advAsk');

$this->assertContains('Answer', $this->CT->getOutput());
}

/**
* Test the choice question functionality
*
* @return void
* @author Dan Cox
*/
public function test_choiceQuestion()
{
$this->CT->setInput("two\n");
$this->CT->execute('Fake:choice');

$this->assertContains('You have selected two', $this->CT->getOutput());
}

} // END class QuestionTest extends \PHPUnit_Framework_TestCase

0 comments on commit 6af4e5f

Please sign in to comment.