![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/codeception/codeception/src/Codeception/Test/ |
<?php declare(strict_types=1); namespace Codeception\Test; use Behat\Gherkin\Node\FeatureNode; use Behat\Gherkin\Node\ScenarioInterface; use Behat\Gherkin\Node\ScenarioNode; use Behat\Gherkin\Node\StepNode; use Behat\Gherkin\Node\TableNode; use Codeception\Lib\Di; use Codeception\Lib\Generator\GherkinSnippets; use Codeception\Scenario; use Codeception\Step\Comment; use Codeception\Step\Meta; use Codeception\Test\Interfaces\Reported; use Codeception\Test\Interfaces\ScenarioDriven; use Exception; use function array_merge; use function array_pop; use function array_shift; use function basename; use function call_user_func_array; use function count; use function explode; use function file_get_contents; use function is_array; use function is_string; use function preg_match; use function var_export; class Gherkin extends Test implements ScenarioDriven, Reported { protected array $steps = []; protected FeatureNode $featureNode; protected ScenarioInterface $scenarioNode; protected Scenario $scenario; public function __construct(FeatureNode $featureNode, ScenarioInterface $scenarioNode, array $steps = []) { $this->featureNode = $featureNode; $this->scenarioNode = $scenarioNode; $this->steps = $steps; $this->setMetadata(new Metadata()); $this->scenario = new Scenario($this); $this->getMetadata()->setName($scenarioNode->getTitle()); $this->getMetadata()->setFeature((string)$featureNode->getTitle()); $this->getMetadata()->setFilename($featureNode->getFile()); } public function __clone(): void { $this->scenario = clone $this->scenario; } public function preload(): void { $this->getMetadata()->setGroups($this->featureNode->getTags()); $this->getMetadata()->setGroups($this->scenarioNode->getTags()); $this->scenario->setMetaStep(null); if (($background = $this->featureNode->getBackground()) !== null) { foreach ($background->getSteps() as $step) { $this->validateStep($step); } } foreach ($this->scenarioNode->getSteps() as $step) { $this->validateStep($step); } if ($this->getMetadata()->getIncomplete()) { $this->getMetadata()->setIncomplete($this->getMetadata()->getIncomplete() . "\nRun gherkin:snippets to define missing steps"); } } public function getSignature(): string { return basename($this->getFileName(), '.feature') . ':' . $this->getScenarioTitle(); } public function test(): void { $this->makeContexts(); $description = explode("\n", (string)$this->featureNode->getDescription()); foreach ($description as $line) { $this->getScenario()->runStep(new Comment($line)); } if (($background = $this->featureNode->getBackground()) !== null) { foreach ($background->getSteps() as $step) { $this->runStep($step); } } foreach ($this->scenarioNode->getSteps() as $step) { $this->runStep($step); } } protected function validateStep(StepNode $stepNode): void { $stepText = $stepNode->getText(); if (GherkinSnippets::stepHasPyStringArgument($stepNode)) { $stepText .= ' ""'; } $matches = []; foreach ($this->steps as $pattern => $context) { $res = preg_match($pattern, $stepText); if (!$res) { continue; } $matches[$pattern] = $context; } if ($matches === []) { // There were no matches, meaning that the user should first add a step definition for this step $incomplete = $this->getMetadata()->getIncomplete(); $this->getMetadata()->setIncomplete("{$incomplete}\nStep definition for `{$stepText}` not found in contexts"); } if (count($matches) > 1) { // There were more than one match, meaning that we don't know which step definition to execute for this step $incomplete = $this->getMetadata()->getIncomplete(); $matchingDefinitions = []; foreach ($matches as $pattern => $context) { $matchingDefinitions[] = '- ' . $pattern . ' (' . self::contextAsString($context) . ')'; } $this->getMetadata()->setIncomplete( "{$incomplete}\nAmbiguous step: `{$stepText}` matches multiple definitions:\n" . implode("\n", $matchingDefinitions) ); } } private function contextAsString($context): string { if (is_array($context) && count($context) === 2) { [$class, $method] = $context; if (is_string($class) && is_string($method)) { return $class . ':' . $method; } } return var_export($context, true); } protected function runStep(StepNode $stepNode): void { $params = []; if ($stepNode->hasArguments()) { $args = $stepNode->getArguments(); $table = $args[0]; if ($table instanceof TableNode) { $params = [$table->getTableAsString()]; } } $meta = new Meta($stepNode->getText(), $params); $meta->setPrefix($stepNode->getKeyword()); $this->scenario->setMetaStep($meta); // enable metastep $stepText = $stepNode->getText(); $hasPyStringArg = GherkinSnippets::stepHasPyStringArgument($stepNode); if ($hasPyStringArg) { // pretend it is inline argument $stepText .= ' ""'; } $this->getScenario()->comment(''); // make metastep to be printed even if no steps in it foreach ($this->steps as $pattern => $context) { $matches = []; if (!preg_match($pattern, $stepText, $matches)) { continue; } array_shift($matches); if ($hasPyStringArg) { // get rid off last fake argument array_pop($matches); } if ($stepNode->hasArguments()) { $matches = array_merge($matches, $stepNode->getArguments()); } call_user_func_array($context, $matches); // execute the step break; } $this->scenario->setMetaStep(null); // disable metastep } protected function makeContexts(): void { /** @var Di $di */ $di = $this->getMetadata()->getService('di'); $di->set($this->getScenario()); $actorClass = $this->getMetadata()->getCurrent('actor'); if ($actorClass) { $di->instantiate($actorClass); } foreach ($this->steps as $pattern => $step) { $di->instantiate($step[0]); $this->steps[$pattern][0] = $di->get($step[0]); } } public function toString(): string { return $this->getFeature() . ': ' . $this->getScenarioTitle(); } public function getFeature(): string { return $this->getMetadata()->getFeature(); } public function getScenarioTitle(): string { return $this->getMetadata()->getName(); } public function getScenario(): Scenario { return $this->scenario; } public function getScenarioText(string $format = 'text'): string { $fileName = $this->getFileName(); if (!$scenarioText = file_get_contents($fileName)) { throw new Exception("Could not get scenario {$fileName}, please check its permissions."); } return $scenarioText; } public function getSourceCode(): string { return ''; } public function getScenarioNode(): ScenarioNode { return $this->scenarioNode; } public function getFeatureNode(): FeatureNode { return $this->featureNode; } /** * Field values for XML reports * * @return array<string, string> */ public function getReportFields(): array { return [ 'name' => $this->toString(), 'feature' => $this->getFeature(), 'file' => $this->getFileName(), ]; } }