Пример #1
0
 /**
  * Render a failed generator threw() verification.
  *
  * @param Spy|Call                            $subject     The subject.
  * @param Cardinality                         $cardinality The cardinality.
  * @param Matcher|Exception|Error|string|null $type        The type of exception.
  *
  * @return string The rendered failure message.
  */
 public function renderGeneratorThrew($subject, Cardinality $cardinality, $type)
 {
     $isCall = $subject instanceof Call;
     if ($isCall) {
         $calls = array($subject);
         $renderedCallee = $this->exporter->exportCallable($subject->callback());
     } else {
         $calls = $subject->allCalls();
         $renderedCallee = $this->exporter->exportCallable($subject);
     }
     $renderedSubject = $this->bold . $renderedCallee . $this->reset;
     $minimum = $cardinality->minimum();
     $maximum = $cardinality->maximum();
     $isNever = null !== $maximum && $maximum < 1;
     if ($isCall) {
         $totalCount = 1;
         $iterableCount = 1;
         $renderedIterableCount = '';
     } else {
         $iterableCount = 0;
         foreach ($calls as $call) {
             if ($call->isGenerator()) {
                 ++$iterableCount;
             }
         }
         $totalCount = $iterableCount;
         if ($cardinality->matches($iterableCount, $iterableCount)) {
             $iterableResultStart = $this->passStart;
         } else {
             $iterableResultStart = $this->failStart;
         }
         $matchOrMatches = 1 === $iterableCount ? 'match' : 'matches';
         $renderedIterableCount = ' ' . $iterableResultStart . $this->faint . '(' . $iterableCount . ' ' . $matchOrMatches . ')' . $this->reset;
     }
     if ($iterableCount xor $isNever) {
         $iterableResult = $this->pass;
     } else {
         $iterableResult = $this->fail;
     }
     if ($type instanceof Matcher) {
         $renderedType = $type->describe($this->exporter);
     } elseif (is_string($type)) {
         $renderedType = $type;
     } else {
         $renderedType = '<any>';
     }
     $renderedCriteria = 'behave like:' . PHP_EOL . '    ' . $iterableResult . ' Returned Generator, then:' . $renderedIterableCount . PHP_EOL . '        ' . $this->fail . ' Threw ' . $renderedType;
     if ($isCall) {
         if ($isNever) {
             $expected = 'Expected ' . $renderedSubject . ' call #' . $subject->index() . ' not to ' . $renderedCriteria;
         } else {
             $expected = 'Expected ' . $renderedSubject . ' call #' . $subject->index() . ' to ' . $renderedCriteria;
         }
     } else {
         if ($isNever) {
             $expected = 'Expected ' . $renderedSubject . ' generator calls not to ' . $renderedCriteria;
         } elseif ($cardinality->isAlways()) {
             $expected = 'Expected all ' . $renderedSubject . ' generator calls to ' . $renderedCriteria;
         } else {
             $expected = 'Expected ' . $renderedSubject . ' generator calls to ' . $renderedCriteria;
         }
     }
     $renderedCalls = array();
     $matchCount = 0;
     foreach ($calls as $call) {
         $callIsRelevant = $call->isGenerator();
         if ($callIsRelevant) {
             $callStart = '';
             $callEnd = '';
         } else {
             $callStart = $this->faint;
             $callEnd = $this->reset;
         }
         $isMatchingCall = false;
         $renderedArguments = array();
         foreach ($call->arguments()->all() as $argument) {
             $renderedArguments[] = $this->exporter->export($argument, 0);
         }
         $responseEvent = $call->responseEvent();
         if ($responseEvent instanceof ReturnedEvent) {
             $returnValue = $responseEvent->value();
             if (is_array($returnValue) || $returnValue instanceof Traversable) {
                 $iterableEvents = $call->iterableEvents();
                 $renderedIterableEvents = array();
                 foreach ($iterableEvents as $event) {
                     if ($event instanceof UsedEvent) {
                         $renderedIterableEvents[] = '        - Started iterating';
                     } elseif ($event instanceof ProducedEvent) {
                         $iterableKey = $event->key();
                         $iterableValue = $event->value();
                         $renderedIterableEvents[] = '        - Produced ' . $this->exporter->export($iterableKey) . ' => ' . $this->exporter->export($iterableValue);
                     } elseif ($event instanceof ReceivedEvent) {
                         $iterableValue = $event->value();
                         $renderedIterableEvents[] = '        - Received ' . $this->exporter->export($iterableValue);
                     } elseif ($event instanceof ReceivedExceptionEvent) {
                         $iterableException = $event->exception();
                         $renderedIterableEvents[] = '        - Received exception ' . $this->exporter->export($iterableException);
                     }
                 }
                 $endEvent = $call->endEvent();
                 if (empty($iterableEvents)) {
                     if ($callIsRelevant) {
                         if ($isNever) {
                             $eventResult = $this->pass;
                         } else {
                             $eventResult = $this->fail;
                         }
                     } else {
                         $eventResult = '-';
                     }
                     $renderedIterableEvents[] = '        ' . $eventResult . ' Never started iterating';
                 } elseif ($endEvent instanceof ConsumedEvent) {
                     $renderedIterableEvents[] = '        - Finished iterating';
                 } elseif ($endEvent instanceof ReturnedEvent) {
                     $iterableValue = $endEvent->value();
                     if ($isNever) {
                         $eventResult = $this->pass;
                     } else {
                         $eventResult = $this->fail;
                     }
                     $renderedIterableEvents[] = '        ' . $eventResult . ' Returned ' . $this->exporter->export($iterableValue);
                 } elseif ($endEvent instanceof ThrewEvent) {
                     $iterableException = $endEvent->exception();
                     $renderedIterableException = $this->exporter->export($iterableException);
                     if ($type instanceof Matcher) {
                         $eventIsMatch = $type->matches($iterableException);
                     } elseif (is_string($type)) {
                         $eventIsMatch = is_a($iterableException, $type);
                     } else {
                         $eventIsMatch = true;
                     }
                     if ($eventIsMatch) {
                         ++$matchCount;
                         $isMatchingCall = true;
                     } elseif ($type instanceof EqualToMatcher) {
                         $renderedIterableException = $this->differenceEngine->difference($renderedType, $renderedIterableException);
                     }
                     if ($eventIsMatch xor $isNever) {
                         $eventResult = $this->pass;
                     } else {
                         $eventResult = $this->fail;
                     }
                     $renderedIterableEvents[] = '        ' . $eventResult . ' Threw ' . $renderedIterableException;
                 } else {
                     if ($callIsRelevant) {
                         if ($isNever) {
                             $eventResult = $this->pass;
                         } else {
                             $eventResult = $this->fail;
                         }
                     } else {
                         $eventResult = '-';
                     }
                     $renderedIterableEvents[] = '        ' . $eventResult . ' Never finished iterating';
                 }
                 $renderedResponse = 'Returned ' . $this->exporter->export($returnValue, 0) . ', then:' . $callEnd . PHP_EOL . $callStart . implode($callEnd . PHP_EOL . $callStart, $renderedIterableEvents);
             } else {
                 $renderedResponse = 'Returned ' . $this->exporter->export($returnValue);
             }
         } elseif ($responseEvent instanceof ThrewEvent) {
             $exception = $responseEvent->exception();
             $renderedResponse = 'Threw ' . $this->exporter->export($exception);
         } else {
             $renderedResponse = 'Never responded';
         }
         if ($callIsRelevant) {
             if ($isMatchingCall xor $isNever) {
                 $renderedResult = $this->pass;
             } else {
                 $renderedResult = $this->fail;
             }
         } else {
             $renderedResult = '-';
         }
         $renderedCalls[] = $callStart . $renderedResult . ' Call #' . $call->index() . ' - ' . $renderedCallee . '(' . implode(', ', $renderedArguments) . '):' . $callEnd . PHP_EOL . $callStart . '    ' . $renderedResult . ' ' . $renderedResponse . $callEnd;
     }
     $actual = PHP_EOL . implode(PHP_EOL, $renderedCalls);
     if ($isCall) {
         $cardinality = '';
     } else {
         $cardinality = $this->renderCardinality($minimum, $maximum, $matchCount, $totalCount, $totalCount, false);
     }
     return $this->reset . $expected . $cardinality . $actual;
 }