Skip to content

Commit 967043e

Browse files
committedJul 30, 2020
MQE-2158: support using actions from multiple modules in Suites
1 parent 98d9a3b commit 967043e

File tree

5 files changed

+194
-152
lines changed

5 files changed

+194
-152
lines changed
 

‎src/Magento/FunctionalTestingFramework/Module/MagentoActionProxies.php

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,122 @@
2020
*/
2121
class MagentoActionProxies extends CodeceptionModule
2222
{
23-
// TODO: placeholder for proxy functions currently in MagentoWebDriver (MQE-1904)
23+
/**
24+
* Create an entity
25+
*
26+
* @param string $key StepKey of the createData action.
27+
* @param string $scope
28+
* @param string $entity Name of xml entity to create.
29+
* @param array $dependentObjectKeys StepKeys of other createData actions that are required.
30+
* @param array $overrideFields Array of FieldName => Value of override fields.
31+
* @param string $storeCode
32+
* @return void
33+
*/
34+
public function createEntity(
35+
$key,
36+
$scope,
37+
$entity,
38+
$dependentObjectKeys = [],
39+
$overrideFields = [],
40+
$storeCode = ''
41+
) {
42+
PersistedObjectHandler::getInstance()->createEntity(
43+
$key,
44+
$scope,
45+
$entity,
46+
$dependentObjectKeys,
47+
$overrideFields,
48+
$storeCode
49+
);
50+
}
51+
52+
/**
53+
* Retrieves and updates a previously created entity
54+
*
55+
* @param string $key StepKey of the createData action.
56+
* @param string $scope
57+
* @param string $updateEntity Name of the static XML data to update the entity with.
58+
* @param array $dependentObjectKeys StepKeys of other createData actions that are required.
59+
* @return void
60+
*/
61+
public function updateEntity($key, $scope, $updateEntity, $dependentObjectKeys = [])
62+
{
63+
PersistedObjectHandler::getInstance()->updateEntity(
64+
$key,
65+
$scope,
66+
$updateEntity,
67+
$dependentObjectKeys
68+
);
69+
}
70+
71+
/**
72+
* Performs GET on given entity and stores entity for use
73+
*
74+
* @param string $key StepKey of getData action.
75+
* @param string $scope
76+
* @param string $entity Name of XML static data to use.
77+
* @param array $dependentObjectKeys StepKeys of other createData actions that are required.
78+
* @param string $storeCode
79+
* @param integer $index
80+
* @return void
81+
*/
82+
public function getEntity($key, $scope, $entity, $dependentObjectKeys = [], $storeCode = '', $index = null)
83+
{
84+
PersistedObjectHandler::getInstance()->getEntity(
85+
$key,
86+
$scope,
87+
$entity,
88+
$dependentObjectKeys,
89+
$storeCode,
90+
$index
91+
);
92+
}
93+
94+
/**
95+
* Retrieves and deletes a previously created entity
96+
*
97+
* @param string $key StepKey of the createData action.
98+
* @param string $scope
99+
* @return void
100+
*/
101+
public function deleteEntity($key, $scope)
102+
{
103+
PersistedObjectHandler::getInstance()->deleteEntity($key, $scope);
104+
}
105+
106+
/**
107+
* Retrieves a field from an entity, according to key and scope given
108+
*
109+
* @param string $stepKey
110+
* @param string $field
111+
* @param string $scope
112+
* @return string
113+
*/
114+
public function retrieveEntityField($stepKey, $field, $scope)
115+
{
116+
return PersistedObjectHandler::getInstance()->retrieveEntityField($stepKey, $field, $scope);
117+
}
118+
119+
/**
120+
* Get encrypted value by key
121+
*
122+
* @param string $key
123+
* @return string|null
124+
* @throws TestFrameworkException
125+
*/
126+
public function getSecret($key)
127+
{
128+
return CredentialStore::getInstance()->getSecret($key);
129+
}
130+
131+
/**
132+
* Returns a value to origin of the action
133+
*
134+
* @param mixed $value
135+
* @return mixed
136+
*/
137+
public function return($value)
138+
{
139+
return $value;
140+
}
24141
}

‎src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php

Lines changed: 11 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Codeception\Exception\ModuleConfigException;
1616
use Codeception\Exception\ModuleException;
1717
use Codeception\Util\Uri;
18+
use Codeception\Lib\ModuleContainer;
1819
use Magento\FunctionalTestingFramework\DataTransport\WebApiExecutor;
1920
use Magento\FunctionalTestingFramework\DataTransport\Auth\WebApiAuth;
2021
use Magento\FunctionalTestingFramework\DataTransport\Auth\Tfa\OTP;
@@ -180,6 +181,16 @@ public function _after(TestInterface $test)
180181
// DO NOT RESET SESSIONS
181182
}
182183

184+
/**
185+
* Return ModuleContainer
186+
*
187+
* @return ModuleContainer
188+
*/
189+
public function getModuleContainer()
190+
{
191+
return $this->moduleContainer;
192+
}
193+
183194
/**
184195
* Returns URL of a host.
185196
*
@@ -956,120 +967,6 @@ public function getOTP()
956967
return OTP::getOTP();
957968
}
958969

959-
/**
960-
* Create an entity
961-
* TODO: move this function to MagentoActionProxies after MQE-1904
962-
*
963-
* @param string $key StepKey of the createData action.
964-
* @param string $scope
965-
* @param string $entity Name of xml entity to create.
966-
* @param array $dependentObjectKeys StepKeys of other createData actions that are required.
967-
* @param array $overrideFields Array of FieldName => Value of override fields.
968-
* @param string $storeCode
969-
* @return void
970-
*/
971-
public function createEntity(
972-
$key,
973-
$scope,
974-
$entity,
975-
$dependentObjectKeys = [],
976-
$overrideFields = [],
977-
$storeCode = ''
978-
) {
979-
PersistedObjectHandler::getInstance()->createEntity(
980-
$key,
981-
$scope,
982-
$entity,
983-
$dependentObjectKeys,
984-
$overrideFields,
985-
$storeCode
986-
);
987-
}
988-
989-
/**
990-
* Retrieves and updates a previously created entity
991-
* TODO: move this function to MagentoActionProxies after MQE-1904
992-
*
993-
* @param string $key StepKey of the createData action.
994-
* @param string $scope
995-
* @param string $updateEntity Name of the static XML data to update the entity with.
996-
* @param array $dependentObjectKeys StepKeys of other createData actions that are required.
997-
* @return void
998-
*/
999-
public function updateEntity($key, $scope, $updateEntity, $dependentObjectKeys = [])
1000-
{
1001-
PersistedObjectHandler::getInstance()->updateEntity(
1002-
$key,
1003-
$scope,
1004-
$updateEntity,
1005-
$dependentObjectKeys
1006-
);
1007-
}
1008-
1009-
/**
1010-
* Performs GET on given entity and stores entity for use
1011-
* TODO: move this function to MagentoActionProxies after MQE-1904
1012-
*
1013-
* @param string $key StepKey of getData action.
1014-
* @param string $scope
1015-
* @param string $entity Name of XML static data to use.
1016-
* @param array $dependentObjectKeys StepKeys of other createData actions that are required.
1017-
* @param string $storeCode
1018-
* @param integer $index
1019-
* @return void
1020-
*/
1021-
public function getEntity($key, $scope, $entity, $dependentObjectKeys = [], $storeCode = '', $index = null)
1022-
{
1023-
PersistedObjectHandler::getInstance()->getEntity(
1024-
$key,
1025-
$scope,
1026-
$entity,
1027-
$dependentObjectKeys,
1028-
$storeCode,
1029-
$index
1030-
);
1031-
}
1032-
1033-
/**
1034-
* Retrieves and deletes a previously created entity
1035-
* TODO: move this function to MagentoActionProxies after MQE-1904
1036-
*
1037-
* @param string $key StepKey of the createData action.
1038-
* @param string $scope
1039-
* @return void
1040-
*/
1041-
public function deleteEntity($key, $scope)
1042-
{
1043-
PersistedObjectHandler::getInstance()->deleteEntity($key, $scope);
1044-
}
1045-
1046-
/**
1047-
* Retrieves a field from an entity, according to key and scope given
1048-
* TODO: move this function to MagentoActionProxies after MQE-1904
1049-
*
1050-
* @param string $stepKey
1051-
* @param string $field
1052-
* @param string $scope
1053-
* @return string
1054-
*/
1055-
public function retrieveEntityField($stepKey, $field, $scope)
1056-
{
1057-
return PersistedObjectHandler::getInstance()->retrieveEntityField($stepKey, $field, $scope);
1058-
}
1059-
1060-
/**
1061-
* Get encrypted value by key
1062-
* TODO: move this function to MagentoActionProxies after MQE-1904
1063-
*
1064-
* @param string $key
1065-
* @return string|null
1066-
* @throws TestFrameworkException
1067-
*/
1068-
public function getSecret($key)
1069-
{
1070-
return CredentialStore::getInstance()->getSecret($key);
1071-
}
1072-
1073970
/**
1074971
* Waits proper amount of time to perform Cron execution
1075972
*
@@ -1122,16 +1019,4 @@ public function switchToIFrame($locator = null)
11221019
$this->webDriver->switchTo()->frame($els[0]);
11231020
}
11241021
}
1125-
1126-
/**
1127-
* Returns a value to origin of the action.
1128-
* TODO: move this function to MagentoActionProxies after MQE-1904
1129-
*
1130-
* @param mixed $value
1131-
* @return mixed
1132-
*/
1133-
public function return($value)
1134-
{
1135-
return $value;
1136-
}
11371022
}

‎src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\FunctionalTestingFramework\Suite\Generators;
88

9+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
910
use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException;
1011
use Magento\FunctionalTestingFramework\Suite\Objects\SuiteObject;
1112
use Magento\FunctionalTestingFramework\Test\Objects\ActionObject;
@@ -32,6 +33,10 @@ class GroupClassGenerator
3233
'comment' => 'print'
3334
];
3435
const GROUP_DIR_NAME = 'Group';
36+
const FUNCTION_PLACEHOLDER = 'PLACEHOLDER';
37+
const FUNCTION_START = 'this->getModuleForAction("';
38+
const FUNCTION_END = '")';
39+
const FUNCTION_REPLACE_REGEX = '/(PLACEHOLDER->([^\(]+))\(/';
3540

3641
/**
3742
* Mustache_Engine instance for template loading
@@ -142,7 +147,7 @@ private function buildHookMustacheArray($hookObj)
142147
//deleteData contains either url or createDataKey, if it contains the former it needs special formatting
143148
if ($action->getType() !== "createData"
144149
&& !array_key_exists(TestGenerator::REQUIRED_ENTITY_REFERENCE, $action->getCustomActionAttributes())) {
145-
$actions = $this->buildWebDriverActionsMustacheArray($action, $actions);
150+
$actions = $this->buildModuleActionsMustacheArray($action, $actions);
146151
continue;
147152
}
148153

@@ -165,22 +170,29 @@ private function buildHookMustacheArray($hookObj)
165170
}
166171

167172
/**
168-
* Takes an action object and array of generated action steps. Converst the action object into generated php and
173+
* Takes an action object and array of generated action steps. Convert the action object into generated php and
169174
* appends the entry to the given array. The result is returned by the function.
170175
*
171176
* @param ActionObject $action
172177
* @param array $actionEntries
173178
* @return array
174179
* @throws TestReferenceException
175180
*/
176-
private function buildWebDriverActionsMustacheArray($action, $actionEntries)
181+
private function buildModuleActionsMustacheArray($action, $actionEntries)
177182
{
178-
$step = TestGenerator::getInstance()->generateStepsPhp([$action], TestGenerator::SUITE_SCOPE, 'webDriver');
183+
$step = TestGenerator::getInstance()->generateStepsPhp(
184+
[$action],
185+
TestGenerator::SUITE_SCOPE,
186+
self::FUNCTION_PLACEHOLDER
187+
);
179188
$rawPhp = str_replace(["\t"], "", $step);
180189
$multipleCommands = explode(PHP_EOL, $rawPhp, -1);
181190
$multipleCommands = array_filter($multipleCommands);
182191
foreach ($multipleCommands as $command) {
183-
$actionEntries = $this->replaceReservedTesterFunctions($command . PHP_EOL, $actionEntries, 'webDriver');
192+
$actionEntries = $this->replaceReservedTesterFunctions(
193+
$command . PHP_EOL, $actionEntries,
194+
self::FUNCTION_PLACEHOLDER
195+
);
184196
}
185197

186198
return $actionEntries;
@@ -204,7 +216,17 @@ private function replaceReservedTesterFunctions($formattedStep, $actionEntries,
204216
$resultingStep = str_replace($testActionCall, $replacement, $formattedStep);
205217
$actionEntries[] = ['action' => $resultingStep];
206218
} else {
207-
$actionEntries[] = ['action' => $formattedStep];
219+
$placeholder = self::FUNCTION_PLACEHOLDER;
220+
$begin = self::FUNCTION_START;
221+
$end = self::FUNCTION_END;
222+
$resultingStep = preg_replace_callback(
223+
self::FUNCTION_REPLACE_REGEX,
224+
function($matches) use ($placeholder, $begin, $end) {
225+
return str_replace($placeholder, $begin . $matches[2] . $end, $matches[1]) . '(';
226+
},
227+
$formattedStep
228+
);
229+
$actionEntries[] = ['action' => $resultingStep];
208230
}
209231
}
210232

‎src/Magento/FunctionalTestingFramework/Suite/views/SuiteClass.mustache

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ use Facebook\WebDriver\Remote\RemoteWebDriver;
66
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler;
77
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore;
88
use Magento\FunctionalTestingFramework\Module\MagentoWebDriver;
9+
use Magento\FunctionalTestingFramework\Module\MagentoAssert;
10+
use Magento\FunctionalTestingFramework\Module\MagentoActionProxies;
11+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
12+
use Codeception\Lib\ModuleContainer;
13+
use Codeception\Module;
914

1015
/**
1116
* Group class is Codeception Extension which is allowed to handle to all internal events.
@@ -30,10 +35,16 @@ class {{suiteName}} extends \Codeception\GroupObject
3035
{{/helpers}}
3136
private static $HOOK_EXECUTION_INIT = "\n/******** Beginning execution of {{suiteName}} suite %s block ********/\n";
3237
private static $HOOK_EXECUTION_END = "\n/******** Execution of {{suiteName}} suite %s block complete ********/\n";
38+
/** @var MagentoWebDriver */
39+
private $webDriver;
40+
/** @var ModuleContainer */
41+
private $moduleContainer;
3342

3443
{{#before}}
3544
public function _before(\Codeception\Event\TestEvent $e)
3645
{
46+
$this->webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
47+
$this->moduleContainer = $this->webDriver->getModuleContainer();
3748
{{#helpers}}
3849
/** @var \Magento\FunctionalTestingFramework\Helper\HelperContainer $helperContainer */
3950
$this->helperContainer = $this->getModule('\Magento\FunctionalTestingFramework\Helper\HelperContainer');
@@ -51,25 +62,21 @@ class {{suiteName}} extends \Codeception\GroupObject
5162
}
5263
}
5364

54-
5565
private function executePreConditions()
5666
{
5767
if ($this->currentTestRun == 1) {
5868
print sprintf(self::$HOOK_EXECUTION_INIT, "before");
5969
60-
/** @var MagentoWebDriver $webDriver */
61-
$webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
62-
6370
try {
6471
{{> testActions}}
6572
} catch (\Exception $exception) {
6673
$this->preconditionFailure = $exception->getMessage();
6774
}
6875

6976
// reset configuration and close session
70-
$webDriver->_resetConfig();
71-
$webDriver->webDriver->close();
72-
$webDriver->webDriver = null;
77+
$this->webDriver->_resetConfig();
78+
$this->webDriver->webDriver->close();
79+
$this->webDriver->webDriver = null;
7380

7481
print sprintf(self::$HOOK_EXECUTION_END, "before");
7582
}
@@ -82,15 +89,11 @@ class {{suiteName}} extends \Codeception\GroupObject
8289
$this->executePostConditions($e);
8390
}
8491

85-
8692
private function executePostConditions(\Codeception\Event\TestEvent $e)
8793
{
8894
if ($this->currentTestRun == $this->testCount) {
8995
print sprintf(self::$HOOK_EXECUTION_INIT, "after");
9096
91-
/** @var MagentoWebDriver $webDriver */
92-
$webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver');
93-
9497
try {
9598
// Find out if Test in Suite failed, will cause potential failures in suite after
9699
$cest = $e->getTest();
@@ -120,7 +123,7 @@ class {{suiteName}} extends \Codeception\GroupObject
120123

121124
PersistedObjectHandler::getInstance()->clearSuiteObjects();
122125

123-
$this->closeSession($webDriver);
126+
$this->closeSession($this->webDriver);
124127

125128
print sprintf(self::$HOOK_EXECUTION_END, "after");
126129
}
@@ -131,13 +134,12 @@ class {{suiteName}} extends \Codeception\GroupObject
131134
* Close session method closes current session.
132135
* If config 'close_all_sessions' is set to 'true' all sessions will be closed.
133136
*
134-
* @param MagentoWebDriver $webDriver
135137
* return void
136138
*/
137-
private function closeSession(MagentoWebDriver $webDriver): void
139+
private function closeSession(): void
138140
{
139-
$webDriverConfig = $webDriver->_getConfig();
140-
$webDriver->_closeSession();
141+
$webDriverConfig = $this->webDriver->_getConfig();
142+
$this->webDriver->_closeSession();
141143
if (isset($webDriverConfig['close_all_sessions']) && $webDriverConfig['close_all_sessions'] === "true") {
142144
$wdHost = sprintf(
143145
'%s://%s:%s%s',
@@ -153,4 +155,20 @@ class {{suiteName}} extends \Codeception\GroupObject
153155
}
154156
}
155157
}
158+
159+
/**
160+
* Return the module for an action.
161+
*
162+
* @param string $action
163+
* @return Module
164+
* @throws \Exception
165+
*/
166+
private function getModuleForAction($action)
167+
{
168+
$module = $this->moduleContainer->moduleForAction($action);
169+
if ($module === null) {
170+
throw new TestFrameworkException('Invalid action "' . $action . '"' . PHP_EOL);
171+
}
172+
return $module;
173+
}
156174
}

‎src/Magento/FunctionalTestingFramework/Suite/views/partials/testActions.mustache

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{{#actions}}
22
{{#webDriverInit}}
3-
if ($webDriver->webDriver != null) {
4-
$webDriver->_restart();
3+
if ($this->webDriver->webDriver != null) {
4+
$this->webDriver->_restart();
55
} else {
6-
$webDriver->_initializeSession();
6+
$this->webDriver->_initializeSession();
77
}
88
{{/webDriverInit}}
99
{{#action}}

0 commit comments

Comments
 (0)
Please sign in to comment.