diff --git a/app/config.php b/app/config.php index b7bede9d..d82897da 100644 --- a/app/config.php +++ b/app/config.php @@ -30,6 +30,7 @@ use PhpSchool\PhpWorkshop\Listener\CodePatchListener; use PhpSchool\PhpWorkshop\Listener\ConfigureCommandListener; use PhpSchool\PhpWorkshop\Listener\PrepareSolutionListener; +use PhpSchool\PhpWorkshop\Listener\RealPathListener; use PhpSchool\PhpWorkshop\Listener\SelfCheckListener; use PhpSchool\PhpWorkshop\MenuItem\ResetProgress; use PhpSchool\PhpWorkshop\Output\OutputInterface; @@ -197,7 +198,8 @@ $c->get(RunnerManager::class) ); }, - + RealPathListener::class => object(), + //checks FileExistsCheck::class => object(), PhpLintCheck::class => object(), @@ -281,6 +283,20 @@ ], 'appContributors' => [], 'eventListeners' => [ + 'realpath-student-submission' => [ + 'cli.verify.start' => [ + containerListener(RealPathListener::class) + ], + 'cli.run.start' => [ + containerListener(RealPathListener::class) + ], + 'cgi.verify.start' => [ + containerListener(RealPathListener::class) + ], + 'cgi.run.start' => [ + containerListener(RealPathListener::class) + ] + ], 'check-exercise-assigned' => [ 'route.pre.resolve.args' => [ containerListener(CheckExerciseAssignedListener::class) @@ -292,25 +308,43 @@ ], ], 'prepare-solution' => [ - 'verify.start' => [ + 'cli.verify.start' => [ + containerListener(PrepareSolutionListener::class), + ], + 'cli.run.start' => [ + containerListener(PrepareSolutionListener::class), + ], + 'cgi.verify.start' => [ containerListener(PrepareSolutionListener::class), ], - 'run.start' => [ + 'cgi.run.start' => [ containerListener(PrepareSolutionListener::class), ], ], 'code-patcher' => [ - 'run.start' => [ + 'cli.verify.start' => [ containerListener(CodePatchListener::class, 'patch'), ], - 'verify.pre.execute' => [ + 'cli.verify.finish' => [ containerListener(CodePatchListener::class, 'patch'), ], - 'verify.post.execute' => [ - containerListener(CodePatchListener::class, 'revert'), + 'cli.run.start' => [ + containerListener(CodePatchListener::class, 'patch'), + ], + 'cli.run.finish' => [ + containerListener(CodePatchListener::class, 'patch'), + ], + 'cgi.verify.start' => [ + containerListener(CodePatchListener::class, 'patch'), ], - 'run.finish' => [ - containerListener(CodePatchListener::class, 'revert'), + 'cgi.verify.finish' => [ + containerListener(CodePatchListener::class, 'patch'), + ], + 'cgi.run.start' => [ + containerListener(CodePatchListener::class, 'patch'), + ], + 'cgi.run.finish' => [ + containerListener(CodePatchListener::class, 'patch'), ], ], 'self-check' => [ diff --git a/src/Command/RunCommand.php b/src/Command/RunCommand.php index 445b263f..b8a5820f 100644 --- a/src/Command/RunCommand.php +++ b/src/Command/RunCommand.php @@ -61,15 +61,7 @@ public function __construct( */ public function __invoke(Input $input) { - $program = $input->getArgument('program'); - if (!file_exists($program)) { - $this->output->printError( - sprintf('Could not run. File: "%s" does not exist', $program) - ); - return 1; - } - $program = realpath($program); $exercise = $this->exerciseRepository->findByName($this->userState->getCurrentExercise()); - $this->exerciseDispatcher->run($exercise, $program, $this->output); + $this->exerciseDispatcher->run($exercise, $input, $this->output); } } diff --git a/src/Command/VerifyCommand.php b/src/Command/VerifyCommand.php index dc511bf7..b98baf1c 100644 --- a/src/Command/VerifyCommand.php +++ b/src/Command/VerifyCommand.php @@ -79,15 +79,6 @@ public function __construct( */ public function __invoke(Input $input) { - $program = $input->getArgument('program'); - if (!file_exists($program)) { - $this->output->printError( - sprintf('Could not verify. File: "%s" does not exist', $program) - ); - return 1; - } - $program = realpath($program); - $exercise = $this->exerciseRepository->findByName($this->userState->getCurrentExercise()); $results = $this->exerciseDispatcher->verify($exercise, $input); diff --git a/src/Event/ExerciseRunnerEvent.php b/src/Event/ExerciseRunnerEvent.php new file mode 100644 index 00000000..6c927875 --- /dev/null +++ b/src/Event/ExerciseRunnerEvent.php @@ -0,0 +1,55 @@ + + */ +class ExerciseRunnerEvent extends Event +{ + + /** + * @var ExerciseInterface + */ + private $exercise; + + /** + * @var Input + */ + private $input; + + /** + * @param string $name + * @param ExerciseInterface $exercise + * @param Input $input + * @param array $parameters + */ + public function __construct($name, ExerciseInterface $exercise, Input $input, array $parameters = []) + { + $parameters['input'] = $input; + $parameters['exercise'] = $exercise; + parent::__construct($name, $parameters); + + $this->exercise = $exercise; + $this->input = $input; + } + + /** + * @return Input + */ + public function getInput() + { + return $this->input; + } + + /** + * @return ExerciseInterface + */ + public function getExercise() + { + return $this->exercise; + } +} diff --git a/src/ExerciseRunner/CgiRunner.php b/src/ExerciseRunner/CgiRunner.php index c709be16..cae02576 100644 --- a/src/ExerciseRunner/CgiRunner.php +++ b/src/ExerciseRunner/CgiRunner.php @@ -8,13 +8,12 @@ use PhpSchool\PhpWorkshop\Event\CgiExecuteEvent; use PhpSchool\PhpWorkshop\Event\Event; use PhpSchool\PhpWorkshop\Event\EventDispatcher; +use PhpSchool\PhpWorkshop\Event\ExerciseRunnerEvent; use PhpSchool\PhpWorkshop\Exception\CodeExecutionException; use PhpSchool\PhpWorkshop\Exception\SolutionExecutionException; use PhpSchool\PhpWorkshop\Exercise\CgiExercise; -use PhpSchool\PhpWorkshop\ExerciseDispatcher; use PhpSchool\PhpWorkshop\Input\Input; use PhpSchool\PhpWorkshop\Output\OutputInterface; -use PhpSchool\PhpWorkshop\Result\CgiOutFailure; use PhpSchool\PhpWorkshop\Result\CgiOutRequestFailure; use PhpSchool\PhpWorkshop\Result\CgiOutResult; use PhpSchool\PhpWorkshop\Result\Failure; @@ -237,7 +236,8 @@ private function getProcess($fileName, RequestInterface $request) */ public function verify(Input $input) { - return new CgiOutResult( + $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cgi.verify.start', $this->exercise, $input)); + $result = new CgiOutResult( $this->getName(), array_map( function (RequestInterface $request) use ($input) { @@ -246,6 +246,8 @@ function (RequestInterface $request) use ($input) { $this->exercise->getRequests() ) ); + $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cgi.verify.finish', $this->exercise, $input)); + return $result; } /** @@ -267,6 +269,7 @@ function (RequestInterface $request) use ($input) { */ public function run(Input $input, OutputInterface $output) { + $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cgi.run.start', $this->exercise, $input)); $success = true; foreach ($this->exercise->getRequests() as $i => $request) { $event = $this->eventDispatcher->dispatch( @@ -295,6 +298,7 @@ public function run(Input $input, OutputInterface $output) $output->lineBreak(); } + $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cgi.run.finish', $this->exercise, $input)); return $success; } } diff --git a/src/ExerciseRunner/CliRunner.php b/src/ExerciseRunner/CliRunner.php index dfac049f..3bb760e9 100644 --- a/src/ExerciseRunner/CliRunner.php +++ b/src/ExerciseRunner/CliRunner.php @@ -8,10 +8,10 @@ use PhpSchool\PhpWorkshop\Event\CliExecuteEvent; use PhpSchool\PhpWorkshop\Event\Event; use PhpSchool\PhpWorkshop\Event\EventDispatcher; +use PhpSchool\PhpWorkshop\Event\ExerciseRunnerEvent; use PhpSchool\PhpWorkshop\Exception\CodeExecutionException; use PhpSchool\PhpWorkshop\Exception\SolutionExecutionException; use PhpSchool\PhpWorkshop\Exercise\CliExercise; -use PhpSchool\PhpWorkshop\ExerciseDispatcher; use PhpSchool\PhpWorkshop\Input\Input; use PhpSchool\PhpWorkshop\Output\OutputInterface; use PhpSchool\PhpWorkshop\Result\Failure; @@ -127,6 +127,18 @@ private function getPhpProcess($fileName, ArrayObject $args) * @return ResultInterface The result of the check. */ public function verify(Input $input) + { + $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.verify.start', $this->exercise, $input)); + $result = $this->doVerify($input); + $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.verify.finish', $this->exercise, $input)); + return $result; + } + + /** + * @param Input $input + * @return ResultInterface + */ + private function doVerify(Input $input) { //arrays are not pass-by-ref $args = new ArrayObject($this->exercise->getArgs()); @@ -175,6 +187,7 @@ public function verify(Input $input) */ public function run(Input $input, OutputInterface $output) { + $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.run.start', $this->exercise, $input)); /** @var CliExecuteEvent $event */ $event = $this->eventDispatcher->dispatch( new CliExecuteEvent('cli.run.student-execute.pre', new ArrayObject($this->exercise->getArgs())) @@ -200,6 +213,7 @@ public function run(Input $input, OutputInterface $output) $output->writeLine($outputBuffer); }); + $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.run.finish', $this->exercise, $input)); return $process->isSuccessful(); } } diff --git a/src/Listener/CodePatchListener.php b/src/Listener/CodePatchListener.php index 9c82aa3c..f0603e54 100644 --- a/src/Listener/CodePatchListener.php +++ b/src/Listener/CodePatchListener.php @@ -4,6 +4,7 @@ use PhpSchool\PhpWorkshop\CodePatcher; use PhpSchool\PhpWorkshop\Event\Event; +use PhpSchool\PhpWorkshop\Event\ExerciseRunnerEvent; use PhpSchool\PhpWorkshop\Input\Input; use RuntimeException; @@ -34,34 +35,28 @@ public function __construct(CodePatcher $codePatcher) } /** - * @param Event $event + * @param ExerciseRunnerEvent $event */ - public function patch(Event $event) + public function patch(ExerciseRunnerEvent $event) { - /** @var Input $input */ - $input = $event->getParameter('input'); - $fileName = $input->getArgument('program'); + $fileName = $event->getInput()->getArgument('program'); $this->originalCode = file_get_contents($fileName); file_put_contents( $fileName, - $this->codePatcher->patch($event->getParameter('exercise'), $this->originalCode) + $this->codePatcher->patch($event->getExercise(), $this->originalCode) ); } /** - * @param Event $event + * @param ExerciseRunnerEvent $event */ - public function revert(Event $event) + public function revert(ExerciseRunnerEvent $event) { if (null === $this->originalCode) { throw new RuntimeException('Can only revert previously patched code'); } - /** @var Input $input */ - $input = $event->getParameter('input'); - $fileName = $input->getArgument('program'); - - file_put_contents($fileName, $this->originalCode); + file_put_contents($event->getInput()->getArgument('program'), $this->originalCode); } } diff --git a/src/Listener/PrepareSolutionListener.php b/src/Listener/PrepareSolutionListener.php index 84e737ff..f8f777ad 100644 --- a/src/Listener/PrepareSolutionListener.php +++ b/src/Listener/PrepareSolutionListener.php @@ -3,6 +3,7 @@ namespace PhpSchool\PhpWorkshop\Listener; use PhpSchool\PhpWorkshop\Event\Event; +use PhpSchool\PhpWorkshop\Event\ExerciseRunnerEvent; use RuntimeException; use Symfony\Component\Process\Process; @@ -25,11 +26,11 @@ class PrepareSolutionListener ]; /** - * @param Event $event + * @param ExerciseRunnerEvent $event */ - public function __invoke(Event $event) + public function __invoke(ExerciseRunnerEvent $event) { - $solution = $event->getParameter('exercise')->getSolution(); + $solution = $event->getExercise()->getSolution(); if ($solution->hasComposerFile()) { //prepare composer deps diff --git a/src/Listener/RealPathListener.php b/src/Listener/RealPathListener.php new file mode 100644 index 00000000..a2c12a03 --- /dev/null +++ b/src/Listener/RealPathListener.php @@ -0,0 +1,28 @@ + + */ +class RealPathListener +{ + + /** + * @param ExerciseRunnerEvent $event + */ + public function __invoke(ExerciseRunnerEvent $event) + { + $program = $event->getInput()->getArgument('program'); + + if (file_exists($program)) { + $event->getInput()->setArgument('program', realpath($program)); + } + } +} diff --git a/test/Command/RunCommandTest.php b/test/Command/RunCommandTest.php new file mode 100644 index 00000000..440c041d --- /dev/null +++ b/test/Command/RunCommandTest.php @@ -0,0 +1,40 @@ + + */ +class RunCommandTest extends PHPUnit_Framework_TestCase +{ + public function test() + { + $input = new Input('appName', ['program' => 'solution.php']); + + $exercise = new CliExerciseImpl; + $repo = new ExerciseRepository([$exercise]); + + $state = new UserState; + $state->setCurrentExercise('my-exercise'); + $color = new Color; + $color->setForceStyle(true); + $output = new StdOutput($color, $this->createMock(TerminalInterface::class)); + + $dispatcher = $this->prophesize(ExerciseDispatcher::class); + $dispatcher->run($exercise, $input, $output)->shouldBeCalled(); + + $command = new RunCommand($repo, $dispatcher->reveal(), $state, $output); + $command->__invoke($input); + } +} diff --git a/test/Command/VerifyCommandTest.php b/test/Command/VerifyCommandTest.php index 596b8de7..dd8ddd3b 100644 --- a/test/Command/VerifyCommandTest.php +++ b/test/Command/VerifyCommandTest.php @@ -5,16 +5,12 @@ use Colors\Color; use PhpSchool\CliMenu\Terminal\TerminalInterface; use PhpSchool\PhpWorkshop\Check\CheckInterface; -use PhpSchool\PhpWorkshop\Exercise\ExerciseType; use PhpSchool\PhpWorkshop\ExerciseDispatcher; use PhpSchool\PhpWorkshop\Input\Input; -use PhpSchool\PhpWorkshop\Output\OutputInterface; use PhpSchool\PhpWorkshop\Output\StdOutput; use PhpSchool\PhpWorkshopTest\Asset\CliExerciseImpl; -use PhpSchool\PhpWorkshopTest\Asset\CliExerciseInterface; use PHPUnit_Framework_TestCase; use PhpSchool\PhpWorkshop\Command\VerifyCommand; -use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface; use PhpSchool\PhpWorkshop\ExerciseRepository; use PhpSchool\PhpWorkshop\Result\Failure; use PhpSchool\PhpWorkshop\Result\Success; @@ -45,26 +41,6 @@ public function setUp() ->will($this->returnValue('Some Check')); } - public function testVerifyPrintsErrorIfProgramDoesNotExist() - { - $repo = new ExerciseRepository([]); - $state = new UserState; - $output = $this->createMock(OutputInterface::class); - $dispatcher = $this->createMock(ExerciseDispatcher::class); - - $programFile = sprintf('%s/%s/program.php', sys_get_temp_dir(), $this->getName()); - $output - ->expects($this->once()) - ->method('printError') - ->with(sprintf('Could not verify. File: "%s" does not exist', $programFile)); - - $serializer = $this->createMock(UserStateSerializer::class); - $renderer = $this->createMock(ResultsRenderer::class); - - $command = new VerifyCommand($repo, $dispatcher, $state, $serializer, $output, $renderer); - $this->assertSame(1, $command->__invoke(new Input('appName', ['program' => $programFile]))); - } - public function testVerifyAddsCompletedExerciseAndReturnsCorrectCodeOnSuccess() { $file = tempnam(sys_get_temp_dir(), 'pws'); diff --git a/test/Event/ExerciseRunnerEventTest.php b/test/Event/ExerciseRunnerEventTest.php new file mode 100644 index 00000000..ba4b6937 --- /dev/null +++ b/test/Event/ExerciseRunnerEventTest.php @@ -0,0 +1,32 @@ + + */ +class ExerciseRunnerEventTest extends PHPUnit_Framework_TestCase +{ + public function testGetters() + { + $exercise = new CliExerciseImpl; + $input = new Input('app'); + + $event = new ExerciseRunnerEvent('Some Event', $exercise, $input, ['number' => 1]); + self::assertSame($exercise, $event->getExercise()); + self::assertSame($input, $event->getInput()); + self::assertEquals( + [ + 'exercise' => $exercise, + 'input' => $input, + 'number' => 1 + ], + $event->getParameters() + ); + } +} diff --git a/test/ExerciseDispatcherTest.php b/test/ExerciseDispatcherTest.php index 83621364..f0d2eea0 100644 --- a/test/ExerciseDispatcherTest.php +++ b/test/ExerciseDispatcherTest.php @@ -51,6 +51,20 @@ public function setUp() touch($this->file); } + public function testGetEventDispatcher() + { + $eventDispatcher = new EventDispatcher($results = new ResultAggregator); + + $exerciseDispatcher = new ExerciseDispatcher( + $this->prophesize(RunnerManager::class)->reveal(), + $results, + $eventDispatcher, + new CheckRepository + ); + + $this->assertSame($eventDispatcher, $exerciseDispatcher->getEventDispatcher()); + } + public function testRequireCheckThrowsExceptionIfCheckDoesNotExist() { $this->expectException(InvalidArgumentException::class); @@ -173,7 +187,7 @@ public function testVerifyThrowsExceptionIfCheckDoesNotSupportExerciseType() $check = $checkProphecy->reveal(); $runner = $this->prophesize(ExerciseRunnerInterface::class); - $runner->getRequiredChecks()->willReturn([]); + $runner->getRequiredChecks()->willReturn([get_class($check)]); $runnerManager = $this->prophesize(RunnerManager::class); $runnerManager->getRunner($exercise)->willReturn($runner->reveal()); @@ -184,8 +198,6 @@ public function testVerifyThrowsExceptionIfCheckDoesNotSupportExerciseType() new CheckRepository([$check]) ); - $exerciseDispatcher->requireCheck(get_class($check)); - $msg = 'Check: "Some Check" cannot process exercise: "Some Exercise" with type: "CLI"'; $this->expectException(CheckNotApplicableException::class); $this->expectExceptionMessage($msg); @@ -205,7 +217,7 @@ public function testVerifyThrowsExceptionIfExerciseDoesNotImplementCorrectInterf $check = $checkProphecy->reveal(); $runner = $this->prophesize(ExerciseRunnerInterface::class); - $runner->getRequiredChecks()->willReturn([]); + $runner->getRequiredChecks()->willReturn([get_class($check)]); $runnerManager = $this->prophesize(RunnerManager::class); $runnerManager->getRunner($exercise)->willReturn($runner->reveal()); @@ -216,8 +228,6 @@ public function testVerifyThrowsExceptionIfExerciseDoesNotImplementCorrectInterf new CheckRepository([$check]) ); - $exerciseDispatcher->requireCheck(get_class($check)); - $msg = 'Exercise: "Some Exercise" should implement interface: "LolIDoNotExist"'; $this->expectException(ExerciseNotConfiguredException::class); $this->expectExceptionMessage($msg); @@ -239,7 +249,7 @@ public function testVerify() $check = $checkProphecy->reveal(); $runner = $this->prophesize(ExerciseRunnerInterface::class); - $runner->getRequiredChecks()->willReturn([]); + $runner->getRequiredChecks()->willReturn([get_class($check)]); $runner->verify($input)->willReturn(new Success('Success!')); $runnerManager = $this->prophesize(RunnerManager::class); $runnerManager->getRunner($exercise)->willReturn($runner->reveal()); @@ -251,8 +261,6 @@ public function testVerify() new CheckRepository([$check]) ); - $exerciseDispatcher->requireCheck(get_class($check)); - $result = $exerciseDispatcher->verify($exercise, $input); $this->assertInstanceOf(ResultAggregator::class, $result); $this->assertTrue($result->isSuccessful()); @@ -276,7 +284,7 @@ public function testVerifyOnlyRunsRequiredChecks() $check2 = $checkProphecy2->reveal(); $runner = $this->prophesize(ExerciseRunnerInterface::class); - $runner->getRequiredChecks()->willReturn([]); + $runner->getRequiredChecks()->willReturn([get_class($check1)]); $runner->verify($input)->willReturn(new Success('Success!')); $runnerManager = $this->prophesize(RunnerManager::class); $runnerManager->getRunner($exercise)->willReturn($runner->reveal()); @@ -288,13 +296,51 @@ public function testVerifyOnlyRunsRequiredChecks() new CheckRepository([$check1, $check2]) ); - $exerciseDispatcher->requireCheck(get_class($check1)); + $result = $exerciseDispatcher->verify($exercise, $input); + $this->assertInstanceOf(ResultAggregator::class, $result); + $this->assertTrue($result->isSuccessful()); + } + + public function testVerifyWithBeforeAndAfterRequiredChecks() + { + $input = new Input('app', ['program' => $this->file]); + $exercise = new CliExerciseImpl('Some Exercise'); + + $checkProphecy1 = $this->prophesize(SimpleCheckInterface::class); + $checkProphecy1->canRun($exercise->getType())->willReturn(true); + $checkProphecy1->getPosition()->willReturn(SimpleCheckInterface::CHECK_BEFORE); + $checkProphecy1->getExerciseInterface()->willReturn(ExerciseInterface::class); + $checkProphecy1->check($exercise, $input)->willReturn(new Success('Success!')); + + $checkProphecy2 = $this->prophesize(SimpleCheckInterface::class); + $checkProphecy2->canRun($exercise->getType())->willReturn(true); + $checkProphecy2->getPosition()->willReturn(SimpleCheckInterface::CHECK_AFTER); + $checkProphecy2->getExerciseInterface()->willReturn(ExerciseInterface::class); + $checkProphecy2->check($exercise, $input)->willReturn(new Success('Success!')); + + $check1 = $checkProphecy1->reveal(); + $check2 = $checkProphecy2->reveal(); + + $runner = $this->prophesize(ExerciseRunnerInterface::class); + $runner->getRequiredChecks()->willReturn([get_class($check1), get_class($check2)]); + $runner->verify($input)->willReturn(new Success('Success!')); + $runnerManager = $this->prophesize(RunnerManager::class); + $runnerManager->getRunner($exercise)->willReturn($runner->reveal()); + + $exerciseDispatcher = new ExerciseDispatcher( + $runnerManager->reveal(), + new ResultAggregator, + $this->prophesize(EventDispatcher::class)->reveal(), + new CheckRepository([$check1, $check2]) + ); $result = $exerciseDispatcher->verify($exercise, $input); $this->assertInstanceOf(ResultAggregator::class, $result); $this->assertTrue($result->isSuccessful()); + $this->assertCount(3, $result); } + public function testWhenBeforeChecksFailTheyReturnImmediately() { $input = new Input('app', ['program' => $this->file]); @@ -316,7 +362,7 @@ public function testWhenBeforeChecksFailTheyReturnImmediately() $check2 = $checkProphecy2->reveal(); $runner = $this->prophesize(ExerciseRunnerInterface::class); - $runner->getRequiredChecks()->willReturn([]); + $runner->getRequiredChecks()->willReturn([get_class($check1), get_class($check2)]); $runner->verify($input)->shouldNotBeCalled(); $runnerManager = $this->prophesize(RunnerManager::class); $runnerManager->getRunner($exercise)->willReturn($runner->reveal()); @@ -328,9 +374,6 @@ public function testWhenBeforeChecksFailTheyReturnImmediately() new CheckRepository([$check1, $check2]) ); - $exerciseDispatcher->requireCheck(get_class($check1)); - $exerciseDispatcher->requireCheck(get_class($check2)); - $result = $exerciseDispatcher->verify($exercise, $input); $this->assertInstanceOf(ResultAggregator::class, $result); $this->assertFalse($result->isSuccessful()); @@ -432,8 +475,6 @@ public function testRun() $output = $this->prophesize(OutputInterface::class)->reveal(); $exercise = new CliExerciseImpl('Some Exercise'); - - $runner = $this->prophesize(ExerciseRunnerInterface::class); $runner->getRequiredChecks()->willReturn([]); $runner->run($input, $output)->willReturn(true); diff --git a/test/Factory/EventDispatcherFactoryTest.php b/test/Factory/EventDispatcherFactoryTest.php index 4e0b47e7..acc83dbc 100644 --- a/test/Factory/EventDispatcherFactoryTest.php +++ b/test/Factory/EventDispatcherFactoryTest.php @@ -227,11 +227,10 @@ public function testDefaultListenersAreRegisteredFromConfig() $listeners = $this->readAttribute($dispatcher, 'listeners'); - $this->assertArrayHasKey('verify.start', $listeners); - $this->assertArrayHasKey('run.start', $listeners); - $this->assertArrayHasKey('verify.pre.execute', $listeners); - $this->assertArrayHasKey('verify.post.execute', $listeners); - $this->assertArrayHasKey('run.finish', $listeners); + $this->assertArrayHasKey('cli.verify.start', $listeners); + $this->assertArrayHasKey('cli.run.start', $listeners); + $this->assertArrayHasKey('cgi.verify.start', $listeners); + $this->assertArrayHasKey('cgi.run.start', $listeners); $this->assertArrayHasKey('verify.post.check', $listeners); } } diff --git a/test/Listener/CodePatchListenerTest.php b/test/Listener/CodePatchListenerTest.php index 443321e9..f92c814f 100644 --- a/test/Listener/CodePatchListenerTest.php +++ b/test/Listener/CodePatchListenerTest.php @@ -4,6 +4,7 @@ use PhpSchool\PhpWorkshop\CodePatcher; use PhpSchool\PhpWorkshop\Event\Event; +use PhpSchool\PhpWorkshop\Event\ExerciseRunnerEvent; use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface; use PhpSchool\PhpWorkshop\Input\Input; use PhpSchool\PhpWorkshop\Listener\CodePatchListener; @@ -49,7 +50,7 @@ public function testRevertThrowsExceptionIfPatchNotPreviouslyCalled() $exercise = $this->createMock(ExerciseInterface::class); $listener = new CodePatchListener($this->codePatcher); - $event = new Event('event', compact('exercise', 'input')); + $event = new ExerciseRunnerEvent('event', $exercise, $input); $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Can only revert previously patched code'); @@ -70,7 +71,7 @@ public function testPatchUpdatesCode() ->will($this->returnValue('MODIFIED CONTENT')); $listener = new CodePatchListener($this->codePatcher); - $event = new Event('event', compact('exercise', 'input')); + $event = new ExerciseRunnerEvent('event', $exercise, $input); $listener->patch($event); $this->assertStringEqualsFile($this->file, 'MODIFIED CONTENT'); @@ -90,7 +91,7 @@ public function testRevertAfterPatch() ->will($this->returnValue('MODIFIED CONTENT')); $listener = new CodePatchListener($this->codePatcher); - $event = new Event('event', compact('exercise', 'input')); + $event = new ExerciseRunnerEvent('event', $exercise, $input); $listener->patch($event); $listener->revert($event); diff --git a/test/Listener/PrepareSolutionListenerTest.php b/test/Listener/PrepareSolutionListenerTest.php index 9eccc2a1..99b85673 100644 --- a/test/Listener/PrepareSolutionListenerTest.php +++ b/test/Listener/PrepareSolutionListenerTest.php @@ -3,8 +3,10 @@ namespace PhpSchool\PhpWorkshopTest\Listener; use PhpSchool\PhpWorkshop\Event\Event; +use PhpSchool\PhpWorkshop\Event\ExerciseRunnerEvent; use PhpSchool\PhpWorkshop\Exercise\CliExercise; use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface; +use PhpSchool\PhpWorkshop\Input\Input; use PhpSchool\PhpWorkshop\Listener\PrepareSolutionListener; use PhpSchool\PhpWorkshop\Solution\SolutionInterface; use PHPUnit_Framework_TestCase; @@ -63,8 +65,8 @@ public function testIfSolutionRequiresComposerButComposerCannotBeLocatedExceptio $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Composer could not be located on the system'); - $e = new Event('epic-event', ['exercise' => $exercise, 'file' => 'file.php']); - $this->listener->__invoke($e); + $event = new ExerciseRunnerEvent('event', $exercise, new Input('app')); + $this->listener->__invoke($event); } public function testIfSolutionRequiresComposerButVendorDirExistsNothingIsDone() @@ -88,8 +90,8 @@ public function testIfSolutionRequiresComposerButVendorDirExistsNothingIsDone() ->method('getBaseDirectory') ->will($this->returnValue(dirname($this->file))); - $e = new Event('epic-event', ['exercise' => $exercise, 'file' => 'file.php']); - $this->listener->__invoke($e); + $event = new ExerciseRunnerEvent('event', $exercise, new Input('app')); + $this->listener->__invoke($event); $this->assertFileExists(sprintf('%s/vendor', dirname($this->file))); //check for non existence of lock file, composer generates this when updating if it doesn't exist @@ -121,8 +123,8 @@ public function testIfSolutionRequiresComposerComposerInstallIsExecuted() ->method('getBaseDirectory') ->will($this->returnValue(dirname($this->file))); - $e = new Event('epic-event', ['exercise' => $exercise, 'file' => 'file.php']); - $this->listener->__invoke($e); + $event = new ExerciseRunnerEvent('event', $exercise, new Input('app')); + $this->listener->__invoke($event); $this->assertFileExists(sprintf('%s/vendor', dirname($this->file))); } diff --git a/test/RealPathListenerTest.php b/test/RealPathListenerTest.php new file mode 100644 index 00000000..ee37856e --- /dev/null +++ b/test/RealPathListenerTest.php @@ -0,0 +1,55 @@ + + */ +class RealPathListenerTest extends PHPUnit_Framework_TestCase +{ + public function testInputArgumentIsReplacesWithAbsolutePathIfFileExists() + { + $current = getcwd(); + + $tempDirectory = sprintf('%s/%s', realpath(sys_get_temp_dir()), $this->getName()); + mkdir($tempDirectory, 0777, true); + chdir($tempDirectory); + touch('test-file.php'); + + $exercise = new CliExerciseImpl; + $input = new Input('app', ['program' => 'test-file.php']); + $listener = new RealPathListener; + $listener->__invoke(new ExerciseRunnerEvent('some.event', $exercise, $input)); + + $this->assertEquals(sprintf('%s/test-file.php', $tempDirectory), $input->getArgument('program')); + + unlink('test-file.php'); + rmdir($tempDirectory); + chdir($current); + } + + public function testInputArgumentIsLeftUnchangedIfFileDoesNotExist() + { + $exercise = new CliExerciseImpl; + $input = new Input('app', ['program' => 'test-file.php']); + $listener = new RealPathListener; + $listener->__invoke(new ExerciseRunnerEvent('some.event', $exercise, $input)); + + $this->assertEquals('test-file.php', $input->getArgument('program')); + } + + private function runInDir($dir, callable $callback) + { + $current = getcwd(); + chdir($dir); + $callback($dir); + chdir($current); + } +}