/**
  * @param Event $event
  */
 public function __invoke(Event $event)
 {
     $exercise = $event->getParameter('exercise');
     if ($exercise instanceof SelfCheck) {
         $this->results->add($exercise->check($event->getParameter('fileName')));
     }
 }
 public function testIterator()
 {
     $results = [new Success($this->check), new Failure($this->check, 'nope')];
     $resultAggregator = new ResultAggregator();
     $resultAggregator->add($results[0]);
     $resultAggregator->add($results[1]);
     $this->assertEquals($results, iterator_to_array($resultAggregator));
 }
예제 #3
0
 /**
  * @param ExerciseInterface $exercise
  * @param string $fileName
  * @return ResultAggregator
  * @throws CheckNotApplicableException
  * @throws ExerciseNotConfiguredException
  */
 public function verify(ExerciseInterface $exercise, $fileName)
 {
     $exercise->configure($this);
     $runner = $this->runnerFactory->create($exercise, $this->eventDispatcher);
     $this->eventDispatcher->dispatch(new Event('verify.start', compact('exercise', 'fileName')));
     $this->validateChecks($this->checksToRunBefore, $exercise);
     $this->validateChecks($this->checksToRunAfter, $exercise);
     foreach ($this->checksToRunBefore as $check) {
         $this->results->add($check->check($exercise, $fileName));
         if (!$this->results->isSuccessful()) {
             return $this->results;
         }
     }
     $this->eventDispatcher->dispatch(new Event('verify.pre.execute', compact('exercise', 'fileName')));
     try {
         $this->results->add($runner->verify($fileName));
     } finally {
         $this->eventDispatcher->dispatch(new Event('verify.post.execute', compact('exercise', 'fileName')));
     }
     foreach ($this->checksToRunAfter as $check) {
         $this->results->add($check->check($exercise, $fileName));
     }
     $this->eventDispatcher->dispatch(new Event('verify.post.check', compact('exercise', 'fileName')));
     $exercise->tearDown();
     $this->eventDispatcher->dispatch(new Event('verify.finish', compact('exercise', 'fileName')));
     return $this->results;
 }
 /**
  * Verify a students solution against a specific exercise. Runs queued checks based on their position. Invokes the
  * correct runner for the exercise based on the exercise type. Various events are triggered throughout the process.
  *
  * @param ExerciseInterface $exercise The exercise instance.
  * @param Input $input The command line arguments passed to the command.
  * @return ResultAggregator Contains all the results injected via the runner, checks and events.
  * @throws CheckNotApplicableException If the check is not applicable to the exercise type.
  * @throws ExerciseNotConfiguredException If the exercise does not implement the correct interface based on
  * the checks required.
  */
 public function verify(ExerciseInterface $exercise, Input $input)
 {
     $exercise->configure($this);
     $runner = $this->runnerManager->getRunner($exercise);
     foreach ($runner->getRequiredChecks() as $requiredCheck) {
         $this->requireCheck($requiredCheck);
     }
     $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.start', $exercise, $input));
     $this->validateChecks($this->checksToRunBefore, $exercise);
     $this->validateChecks($this->checksToRunAfter, $exercise);
     foreach ($this->checksToRunBefore as $check) {
         $this->results->add($check->check($exercise, $input));
         if (!$this->results->isSuccessful()) {
             return $this->results;
         }
     }
     $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.pre.execute', $exercise, $input));
     try {
         $this->results->add($runner->verify($input));
     } finally {
         $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.post.execute', $exercise, $input));
     }
     foreach ($this->checksToRunAfter as $check) {
         $this->results->add($check->check($exercise, $input));
     }
     $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.post.check', $exercise, $input));
     $exercise->tearDown();
     $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.finish', $exercise, $input));
     return $this->results;
 }
예제 #5
0
 public function testVerifyDoesNotAddCompletedExerciseAndReturnsCorrectCodeOnFailure()
 {
     $file = tempnam(sys_get_temp_dir(), 'pws');
     touch($file);
     $input = new Input('appName', ['program' => $file]);
     $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));
     $serializer = $this->createMock(UserStateSerializer::class);
     $serializer->expects($this->never())->method('serialize')->with($state);
     $renderer = $this->createMock(ResultsRenderer::class);
     $results = new ResultAggregator();
     $results->add(new Failure($this->check, 'cba'));
     $dispatcher = $this->createMock(ExerciseDispatcher::class);
     $dispatcher->expects($this->once())->method('verify')->with($exercise, $input)->will($this->returnValue($results));
     $renderer->expects($this->once())->method('render')->with($results, $exercise, $state, $output);
     $command = new VerifyCommand($repo, $dispatcher, $state, $serializer, $output, $renderer);
     $this->assertEquals(1, $command->__invoke($input));
     $this->assertEquals([], $state->getCompletedExercises());
     unlink($file);
 }
예제 #6
0
 /**
  * @param EventInterface $event
  * @return EventInterface
  */
 public function dispatch(EventInterface $event)
 {
     if (array_key_exists($event->getName(), $this->listeners)) {
         foreach ($this->listeners[$event->getName()] as $listener) {
             $listener($event);
         }
     }
     if (array_key_exists($event->getName(), $this->verifiers)) {
         foreach ($this->verifiers[$event->getName()] as $verifier) {
             $result = $verifier($event);
             //return type hints pls
             if ($result instanceof ResultInterface) {
                 $this->resultAggregator->add($result);
             } else {
                 //??!!
             }
         }
     }
     return $event;
 }
예제 #7
0
 /**
  * Insert a verifier callback which will execute at the given event name much like normal listeners.
  * A verifier should return an object which implements `PhpSchool\PhpWorkshop\Result\FailureInterface`
  * or `PhpSchool\PhpWorkshop\Result\SuccessInterface`. This result object will be added to the result aggregator.
  *
  * @param string|array $eventName
  * @param callable $verifier
  */
 public function insertVerifier($eventName, callable $verifier)
 {
     $this->attachListener($eventName, function (EventInterface $event) use($verifier) {
         $result = $verifier($event);
         //return type hints pls
         if ($result instanceof ResultInterface) {
             $this->resultAggregator->add($result);
         } else {
             //??!!
         }
     });
 }
 public function testRenderAllFailures()
 {
     $color = new Color();
     $color->setForceStyle(true);
     $resultRendererFactory = new ResultRendererFactory();
     $resultRendererFactory->registerRenderer(Failure::class, FailureRenderer::class, function (Failure $failure) {
         $renderer = $this->prophesize(FailureRenderer::class);
         $renderer->render(Argument::type(ResultsRenderer::class))->willReturn($failure->getReason() . "\n");
         return $renderer->reveal();
     });
     $terminal = $this->prophesize(TerminalInterface::class);
     $terminal->getWidth()->willReturn(100);
     $terminal = $terminal->reveal();
     $exerciseRepo = $this->prophesize(ExerciseRepository::class);
     $exerciseRepo->count()->willReturn(2);
     $renderer = new ResultsRenderer('app', $color, $terminal, $exerciseRepo->reveal(), (new Factory())->__invoke(), $resultRendererFactory);
     $resultSet = new ResultAggregator();
     $resultSet->add(new Failure('Failure 1', 'Failure 1'));
     $resultSet->add(new Failure('Failure 2', 'Failure 2'));
     $this->expectOutputString($this->getExpectedOutput());
     $renderer->render($resultSet, $this->createMock(ExerciseInterface::class), new UserState(), new StdOutput($color, $terminal));
 }