Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
TestContextExtension.php
Go to the documentation of this file.
1 <?php
8 
9 use Codeception\Events;
11 
17 {
18  const TEST_PHASE_AFTER = "_after";
19 
24  public static $events;
25 
32  public function _initialize()
33  {
34  $events = [
35  Events::TEST_START => 'testStart',
36  Events::TEST_FAIL => 'testFail',
37  Events::STEP_AFTER => 'afterStep',
38  Events::TEST_END => 'testEnd'
39  ];
40  self::$events = array_merge(parent::$events, $events);
41  parent::_initialize();
42  }
43 
49  public function testStart()
50  {
51  PersistedObjectHandler::getInstance()->clearHookObjects();
52  PersistedObjectHandler::getInstance()->clearTestObjects();
53  }
54 
60  public function testFail(\Codeception\Event\FailEvent $e)
61  {
62  $cest = $e->getTest();
63  $context = $this->extractContext($e->getFail()->getTrace(), $cest->getTestMethod());
64  // Do not attempt to run _after if failure was in the _after block
65  // Try to run _after but catch exceptions to prevent them from overwriting original failure.
67  $this->runAfterBlock($e, $cest);
68  }
69  }
70 
77  public function testEnd(\Codeception\Event\TestEvent $e)
78  {
79  $cest = $e->getTest();
80 
81  //Access private TestResultObject to find stack and if there are any errors (as opposed to failures)
82  $testResultObject = call_user_func(\Closure::bind(
83  function () use ($cest) {
84  return $cest->getTestResultObject();
85  },
86  $cest
87  ));
88  $errors = $testResultObject->errors();
89  if (!empty($errors)) {
90  foreach ($errors as $error) {
91  if ($error->failedTest()->getTestMethod() == $cest->getName()) {
92  $stack = $errors[0]->thrownException()->getTrace();
93  $context = $this->extractContext($stack, $cest->getTestMethod());
94  // Do not attempt to run _after if failure was in the _after block
95  // Try to run _after but catch exceptions to prevent them from overwriting original failure.
97  $this->runAfterBlock($e, $cest);
98  }
99  continue;
100  }
101  }
102  }
103  // Reset Session and Cookies after all Test Runs, workaround due to functional.suite.yml restart: true
104  $this->getDriver()->_runAfter($e->getTest());
105  }
106 
113  private function runAfterBlock($e, $cest)
114  {
115  try {
116  $actorClass = $e->getTest()->getMetadata()->getCurrent('actor');
117  $I = new $actorClass($cest->getScenario());
118  call_user_func(\Closure::bind(
119  function () use ($cest, $I) {
120  $cest->executeHook($I, 'after');
121  },
122  null,
123  $cest
124  ));
125  } catch (\Exception $e) {
126  // Do not rethrow Exception
127  }
128  }
129 
136  public function extractContext($trace, $class)
137  {
138  foreach ($trace as $entry) {
139  $traceClass = $entry["class"] ?? null;
140  if (strpos($traceClass, $class) != 0) {
141  return $entry["function"];
142  }
143  }
144  return null;
145  }
146 
155  public function beforeStep(\Codeception\Event\StepEvent $e)
156  {
157  if ($this->pageChanged($e->getStep())) {
158  $this->getDriver()->cleanJsError();
159  }
160  }
161 
169  public function afterStep(\Codeception\Event\StepEvent $e)
170  {
171  ErrorLogger::getInstance()->logErrors($this->getDriver(), $e);
172  }
173 }
$_option $_optionId $class
Definition: date.phtml:13
$errors
Definition: overview.phtml:9