From 64902cf75cab405fad303d1dc07f8219f34bdbd3 Mon Sep 17 00:00:00 2001 From: KevinBKozan Date: Fri, 2 Mar 2018 11:27:30 -0600 Subject: [PATCH 1/6] MQE-697: Grab test actions's results cannot be used in action-groups - actionGroup now loops through known keys and replaces references to them with stepKey . actionGroupKey - added verification tests --- .../ActionGroupWithStepKeyReferences.txt | 37 +++++++++++++++ .../ActionGroup/FunctionalActionGroup.xml | 5 +++ .../TestModule/Test/ActionGroupTest.xml | 4 ++ .../Tests/ActionGroupGenerationTest.php | 11 +++++ .../Test/Objects/ActionGroupObject.php | 45 ++++++++++++++++++- 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt diff --git a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt new file mode 100644 index 000000000..bc2b5ea46 --- /dev/null +++ b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt @@ -0,0 +1,37 @@ +amGoingTo("create entity that has the stepKey: createSimpleDataactionGroup"); + $simpleData = DataObjectHandler::getInstance()->getObject("simpleData"); + $createSimpleDataactionGroup = new DataPersistenceHandler($simpleData, []); + $createSimpleDataactionGroup->createEntity(); + $grabTextDataactionGroup = $I->grabTextFrom(".class"); + $I->fillField(".{$grabTextDataactionGroup}", $createSimpleDataactionGroup->getCreatedDataByName('field')); + } +} diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml index bab09b4af..843c66739 100644 --- a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml @@ -45,4 +45,9 @@ + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml index a8b1c01d9..72617c858 100644 --- a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml @@ -110,4 +110,8 @@ + + + + diff --git a/dev/tests/verification/Tests/ActionGroupGenerationTest.php b/dev/tests/verification/Tests/ActionGroupGenerationTest.php index 3af62eb77..e62ea24a5 100644 --- a/dev/tests/verification/Tests/ActionGroupGenerationTest.php +++ b/dev/tests/verification/Tests/ActionGroupGenerationTest.php @@ -96,4 +96,15 @@ public function testActionGroupWithSimpleDataUsageFromDefaultArgument() { $this->generateAndCompareTest('ActionGroupWithSimpleDataUsageFromDefaultArgument'); } + + /** + * Test generation of a test referencing an action group that uses stepKey references (grabFrom/CreateData) + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testActionGroupWithStepKeyReferences() + { + $this->generateAndCompareTest('ActionGroupWithStepKeyReferences'); + } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php index a8e56f660..800f1f3f2 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php @@ -121,6 +121,7 @@ private function resolveArguments($arguments) private function getResolvedActionsWithArgs($arguments, $actionReferenceKey) { $resolvedActions = []; + $originalStepKeys = $this->extractOriginalStepKeys(); // $regexPattern match on: $matches[0] {{section.element(arg.field)}} // $matches[1] = section.element @@ -151,12 +152,18 @@ private function getResolvedActionsWithArgs($arguments, $actionReferenceKey) } } + $mergedActionAttributes = $this->appendActionGroupKeyToKeyReferences( + array_merge($action->getCustomActionAttributes(), $newActionAttributes), + $originalStepKeys, + $actionReferenceKey + ); + // we append the action reference key to any linked action and the action's merge key as the user might // use this action group multiple times in the same test. $resolvedActions[$action->getStepKey() . $actionReferenceKey] = new ActionObject( $action->getStepKey() . $actionReferenceKey, $action->getType(), - array_merge($action->getCustomActionAttributes(), $newActionAttributes), + $mergedActionAttributes, $action->getLinkedAction() == null ? null : $action->getLinkedAction() . $actionReferenceKey, $action->getOrderOffset() ); @@ -307,6 +314,42 @@ private function replacePersistedArgument($replacement, $attributeValue, $fullVa return $newAttributeValue; } + /** + * Finds and returns all original stepkeys of actions in actionGroup. + * @return string[] + */ + private function extractOriginalStepKeys() + { + $originalKeys = []; + foreach ($this->parsedActions as $action) { + $originalKeys[] = $action->getStepKey(); + } + return $originalKeys; + } + + /** + * Loops through all actionAttributes and searches/replaces stepKey references with concatenated actionGroupKey. + * @param array $actionAttributes + * @param array $actionStepKeys + * @param string $actionGroupKey + * @return array + */ + private function appendActionGroupKeyToKeyReferences($actionAttributes, $actionStepKeys, $actionGroupKey) + { + foreach ($actionAttributes as $attributeKey => $attributeValue) { + foreach ($actionStepKeys as $key) { + if (!is_array($attributeValue) && strpos($attributeValue, $key)) { + $actionAttributes[$attributeKey] = preg_replace( + "/{$key}/", + $key . $actionGroupKey, + $attributeValue + ); + } + } + } + return $actionAttributes; + } + /** * Searches through ActionGroupObject's arguments and returns first argument wi * @param string $name From d192c50a34c894e19afd8625165b5b6ff2b78611 Mon Sep 17 00:00:00 2001 From: KevinBKozan Date: Fri, 2 Mar 2018 12:17:58 -0600 Subject: [PATCH 2/6] MQE-697: Grab test actions's results cannot be used in action-groups - str_replace usage --- .../Test/Objects/ActionGroupObject.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php index 800f1f3f2..9eb847959 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php @@ -339,8 +339,8 @@ private function appendActionGroupKeyToKeyReferences($actionAttributes, $actionS foreach ($actionAttributes as $attributeKey => $attributeValue) { foreach ($actionStepKeys as $key) { if (!is_array($attributeValue) && strpos($attributeValue, $key)) { - $actionAttributes[$attributeKey] = preg_replace( - "/{$key}/", + $actionAttributes[$attributeKey] = str_replace( + $key, $key . $actionGroupKey, $attributeValue ); From 4c94f74715648ac45ffe94854b4fc9891e2b6fbf Mon Sep 17 00:00:00 2001 From: KevinBKozan Date: Wed, 7 Mar 2018 15:36:06 -0600 Subject: [PATCH 3/6] MQE-697: Grab test actions's results cannot be used in action-groups - added actionGroupOrigin to actionObject, keeps track of which actionGroup it came frmo and the test invocation name. - testGenerator actionName no longer exists, now passes and uses actionObject where needed. - replacement of actionGroup key is now done at testgenerator level, not object level. - updated tests to reflect this --- .../Test/Objects/ActionGroupObjectTest.php | 2 +- .../ActionGroupWithStepKeyReferences.txt | 10 +- .../Resources/BasicFunctionalTest.txt | 2 +- .../Resources/PersistenceCustomFieldsTest.txt | 24 +-- .../Test/Objects/ActionGroupObject.php | 47 ++---- .../Test/Objects/ActionObject.php | 22 ++- .../Util/TestGenerator.php | 138 ++++++++++++------ 7 files changed, 141 insertions(+), 104 deletions(-) diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php index bf5eb92e2..8a5ba7100 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php @@ -21,7 +21,7 @@ class ActionGroupObjectTest extends TestCase { - const ACTION_GROUP_MERGE_KEY = 'testKey'; + const ACTION_GROUP_MERGE_KEY = 'TestKey'; /** * Tests a string literal in an action group diff --git a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt index bc2b5ea46..8a56a6906 100644 --- a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt +++ b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt @@ -27,11 +27,11 @@ class ActionGroupWithStepKeyReferencesCest */ public function ActionGroupWithStepKeyReferences(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createSimpleDataactionGroup"); + $I->amGoingTo("create entity that has the stepKey: createSimpleDataActionGroup"); $simpleData = DataObjectHandler::getInstance()->getObject("simpleData"); - $createSimpleDataactionGroup = new DataPersistenceHandler($simpleData, []); - $createSimpleDataactionGroup->createEntity(); - $grabTextDataactionGroup = $I->grabTextFrom(".class"); - $I->fillField(".{$grabTextDataactionGroup}", $createSimpleDataactionGroup->getCreatedDataByName('field')); + $createSimpleDataActionGroup = new DataPersistenceHandler($simpleData, []); + $createSimpleDataActionGroup->createEntity(); + $grabTextDataActionGroup = $I->grabTextFrom(".class"); + $I->fillField(".{$grabTextDataActionGroup}", $createSimpleDataActionGroup->getCreatedDataByName('field')); } } diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt index 4db2d7c6f..3e8f614c2 100644 --- a/dev/tests/verification/Resources/BasicFunctionalTest.txt +++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt @@ -97,7 +97,7 @@ class BasicFunctionalTestCest $grabMultipleKey1 = $I->grabMultiple(".functionalTestSelector"); $grabTextFromKey1 = $I->grabTextFrom(".functionalTestSelector"); $grabValueFromKey1 = $I->grabValueFrom(".functionalTestSelector"); - $magentoCli1 = $I->executeMagentoCLICommand("maintenance:enable"); + $magentoCli1 = $I->magentoCLI("maintenance:enable"); $I->comment($magentoCli1); $I->makeScreenshot("screenShotInput"); $I->maximizeWindow(); diff --git a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt index ef9fdba23..f4d607c0b 100644 --- a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt +++ b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt @@ -68,20 +68,20 @@ class PersistenceCustomFieldsTestCest $UniquePerson = DataObjectHandler::getInstance()->getObject("UniquePerson"); $createdData3 = new DataPersistenceHandler($UniquePerson, [$createdData], $createdData3Fields); $createdData3->createEntity(); - $createDataAG1createdAGFields['firstname'] = "string1"; - $I->amGoingTo("create entity that has the stepKey: createDataAG1createdAG"); + $createDataAG1CreatedAGFields['firstname'] = "string1"; + $I->amGoingTo("create entity that has the stepKey: createDataAG1CreatedAG"); $simpleData = DataObjectHandler::getInstance()->getObject("simpleData"); - $createDataAG1createdAG = new DataPersistenceHandler($simpleData, [], $createDataAG1createdAGFields); - $createDataAG1createdAG->createEntity(); - $createDataAG2createdAGFields['firstname'] = "Jane"; - $I->amGoingTo("create entity that has the stepKey: createDataAG2createdAG"); + $createDataAG1CreatedAG = new DataPersistenceHandler($simpleData, [], $createDataAG1CreatedAGFields); + $createDataAG1CreatedAG->createEntity(); + $createDataAG2CreatedAGFields['firstname'] = "Jane"; + $I->amGoingTo("create entity that has the stepKey: createDataAG2CreatedAG"); $simpleData = DataObjectHandler::getInstance()->getObject("simpleData"); - $createDataAG2createdAG = new DataPersistenceHandler($simpleData, [], $createDataAG2createdAGFields); - $createDataAG2createdAG->createEntity(); - $createDataAG3createdAGFields['firstname'] = $createdData3->getCreatedDataByName('firstname'); - $I->amGoingTo("create entity that has the stepKey: createDataAG3createdAG"); + $createDataAG2CreatedAG = new DataPersistenceHandler($simpleData, [], $createDataAG2CreatedAGFields); + $createDataAG2CreatedAG->createEntity(); + $createDataAG3CreatedAGFields['firstname'] = $createdData3->getCreatedDataByName('firstname'); + $I->amGoingTo("create entity that has the stepKey: createDataAG3CreatedAG"); $simpleData = DataObjectHandler::getInstance()->getObject("simpleData"); - $createDataAG3createdAG = new DataPersistenceHandler($simpleData, [], $createDataAG3createdAGFields); - $createDataAG3createdAG->createEntity(); + $createDataAG3CreatedAG = new DataPersistenceHandler($simpleData, [], $createDataAG3CreatedAGFields); + $createDataAG3CreatedAG->createEntity(); } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php index 9eb847959..90be0a643 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php @@ -15,6 +15,9 @@ */ class ActionGroupObject { + const ACTION_GROUP_ORIGIN_NAME = "actionGroupName"; + const ACTION_GROUP_ORIGIN_TEST_REF = "testInvocationRef"; + /** * Array of variable-enabled attributes. * @var array @@ -121,7 +124,6 @@ private function resolveArguments($arguments) private function getResolvedActionsWithArgs($arguments, $actionReferenceKey) { $resolvedActions = []; - $originalStepKeys = $this->extractOriginalStepKeys(); // $regexPattern match on: $matches[0] {{section.element(arg.field)}} // $matches[1] = section.element @@ -152,20 +154,16 @@ private function getResolvedActionsWithArgs($arguments, $actionReferenceKey) } } - $mergedActionAttributes = $this->appendActionGroupKeyToKeyReferences( - array_merge($action->getCustomActionAttributes(), $newActionAttributes), - $originalStepKeys, - $actionReferenceKey - ); - // we append the action reference key to any linked action and the action's merge key as the user might // use this action group multiple times in the same test. - $resolvedActions[$action->getStepKey() . $actionReferenceKey] = new ActionObject( - $action->getStepKey() . $actionReferenceKey, + $resolvedActions[$action->getStepKey() . ucfirst($actionReferenceKey)] = new ActionObject( + $action->getStepKey() . ucfirst($actionReferenceKey), $action->getType(), - $mergedActionAttributes, - $action->getLinkedAction() == null ? null : $action->getLinkedAction() . $actionReferenceKey, - $action->getOrderOffset() + array_merge($action->getCustomActionAttributes(), $newActionAttributes), + $action->getLinkedAction() == null ? null : $action->getLinkedAction() . ucfirst($actionReferenceKey), + $action->getOrderOffset(), + [self::ACTION_GROUP_ORIGIN_NAME => $this->name, + self::ACTION_GROUP_ORIGIN_TEST_REF => $actionReferenceKey] ); } @@ -318,7 +316,7 @@ private function replacePersistedArgument($replacement, $attributeValue, $fullVa * Finds and returns all original stepkeys of actions in actionGroup. * @return string[] */ - private function extractOriginalStepKeys() + public function extractStepKeys() { $originalKeys = []; foreach ($this->parsedActions as $action) { @@ -327,29 +325,6 @@ private function extractOriginalStepKeys() return $originalKeys; } - /** - * Loops through all actionAttributes and searches/replaces stepKey references with concatenated actionGroupKey. - * @param array $actionAttributes - * @param array $actionStepKeys - * @param string $actionGroupKey - * @return array - */ - private function appendActionGroupKeyToKeyReferences($actionAttributes, $actionStepKeys, $actionGroupKey) - { - foreach ($actionAttributes as $attributeKey => $attributeValue) { - foreach ($actionStepKeys as $key) { - if (!is_array($attributeValue) && strpos($attributeValue, $key)) { - $actionAttributes[$attributeKey] = str_replace( - $key, - $key . $actionGroupKey, - $attributeValue - ); - } - } - } - return $actionAttributes; - } - /** * Searches through ActionGroupObject's arguments and returns first argument wi * @param string $name diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index 63cac272f..fcc42be55 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -84,6 +84,13 @@ class ActionObject */ private $timeout; + /** + * Array with two items, if this actionObject was created as the result of an actionGroup call: + * + * @var array + */ + private $actionGroupOrigin = []; + /** * ActionObject constructor. * @@ -92,18 +99,21 @@ class ActionObject * @param array $actionAttributes * @param string|null $linkedAction * @param string $order + * @param array $actionGroupOrigin */ public function __construct( $stepKey, $type, $actionAttributes, $linkedAction = null, - $order = ActionObject::MERGE_ACTION_ORDER_BEFORE + $order = ActionObject::MERGE_ACTION_ORDER_BEFORE, + $actionGroupOrigin = null ) { $this->stepKey = $stepKey; $this->type = $type; $this->actionAttributes = $actionAttributes; $this->linkedAction = $linkedAction; + $this->actionGroupOrigin = $actionGroupOrigin; if ($order == ActionObject::MERGE_ACTION_ORDER_AFTER) { $this->orderOffset = 1; @@ -130,6 +140,16 @@ public function getType() return $this->type; } + /** + * Getter for actionGroupOrigin + * + * @return string + */ + public function getActionGroupOrigin() + { + return $this->actionGroupOrigin; + } + /** * This function returns an array of action attributes mapped by key. For example * the tag has 3 attributes, diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 3fb679bdf..f4565a9d4 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -8,7 +8,9 @@ use Magento\FunctionalTestingFramework\DataGenerator\Objects\EntityDataObject; use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; +use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler; +use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\TestHookObject; @@ -396,7 +398,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) foreach ($stepsObject as $steps) { $actor = "I"; - $actionName = $steps->getType(); + $actionObject = $steps; $stepKey = $steps->getStepKey(); $customActionAttributes = $steps->getCustomActionAttributes(); $attribute = null; @@ -433,7 +435,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $assertDelta = null; // Validate action attributes and print notice messages on violation. - $this->validateXmlAttributesMutuallyExclusive($stepKey, $actionName, $customActionAttributes); + $this->validateXmlAttributesMutuallyExclusive($stepKey, $actionObject->getType(), $customActionAttributes); if (isset($customActionAttributes['command'])) { $command = $customActionAttributes['command']; @@ -490,7 +492,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $time = $customActionAttributes['timeout']; } - if (isset($customActionAttributes['parameterArray']) && $actionName != 'pressKey') { + if (isset($customActionAttributes['parameterArray']) && $actionObject->getType() != 'pressKey') { // validate the param array is in the correct format $this->validateParameterArray($customActionAttributes['parameterArray']); @@ -579,7 +581,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $visible = $customActionAttributes['visible']; } - switch ($actionName) { + switch ($actionObject->getType()) { case "createData": $entity = $customActionAttributes['entity']; //Add an informative statement to help the user debug test runs @@ -807,7 +809,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "assertArrayIsSorted": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $parameterArray, $this->wrapWithDoubleQuotes($sortOrder) ); @@ -825,11 +827,11 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "typeInPopup": case "dontSee": case "see": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $input, $selector); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $input, $selector); break; case "switchToNextTab": case "switchToPreviousTab": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $this->stripWrappedQuotes($input)); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $this->stripWrappedQuotes($input)); break; case "clickWithLeftButton": case "clickWithRightButton": @@ -838,18 +840,18 @@ private function generateStepsPhp($stepsObject, $hookObject = false) if (!$selector) { $selector = 'null'; } - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $x, $y); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $x, $y); break; case "dontSeeCookie": case "resetCookie": case "seeCookie": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $input, $parameterArray); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $input, $parameterArray); break; case "grabCookie": $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - $actionName, + $actionObject, $input, $parameterArray ); @@ -860,7 +862,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "seeElement": case "seeElementInDOM": case "seeInFormFields": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $parameterArray); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $parameterArray); break; case "pressKey": $parameterArray = $customActionAttributes['parameterArray'] ?? null; @@ -884,22 +886,22 @@ private function generateStepsPhp($stepsObject, $hookObject = false) // put the array together as a string to be passed as args $parameterArray = implode(",", $tmpParameterArray); } - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $input, $parameterArray); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $input, $parameterArray); break; case "selectOption": case "unselectOption": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $input, $parameterArray); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $input, $parameterArray); break; case "submitForm": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $parameterArray, $button); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $parameterArray, $button); break; case "dragAndDrop": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector1, $selector2); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector1, $selector2); break; case "selectMultipleOptions": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $selector1, $selector2, $input, @@ -907,19 +909,19 @@ private function generateStepsPhp($stepsObject, $hookObject = false) ); break; case "executeInSelenium": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $function); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $function); break; case "executeJS": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $function); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $function); break; case "performOn": case "waitForElementChange": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $function, $time); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $function, $time); break; case "waitForJS": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $function, $time ); @@ -929,23 +931,23 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "waitForElement": case "waitForElementVisible": case "waitForElementNotVisible": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $time); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $time); break; case "waitForPageLoad": case "waitForText": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $input, $time, $selector); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $input, $time, $selector); break; case "formatMoney": $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - $actionName, + $actionObject, $input, $locale ); break; case "mSetLocale": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $input, $locale); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $input, $locale); break; case "grabAttributeFrom": case "grabMultiple": @@ -953,7 +955,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - $actionName, + $actionObject, $selector, $input ); @@ -963,7 +965,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - $actionName, + $actionObject, $selector ); break; @@ -971,16 +973,16 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - $actionName + $actionObject ); break; case "resizeWindow": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $width, $height); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $width, $height); break; case "searchAndMultiSelectOption": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $selector, $input, $parameterArray, @@ -989,12 +991,12 @@ private function generateStepsPhp($stepsObject, $hookObject = false) break; case "seeLink": case "dontSeeLink": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $input, $url); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $input, $url); break; case "setCookie": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $selector, $input, $value, @@ -1016,12 +1018,12 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "loadSessionSnapshot": case "seeInField": case "seeOptionIsSelected": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $input); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $input); break; case "seeNumberOfElements": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $selector, $input, $parameterArray @@ -1031,10 +1033,16 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "seeInSource": case "dontSeeInSource": // TODO: Need to fix xml parser to allow parsing html. - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $html); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $html); break; case "conditionalClick": - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $dependentSelector, $visible); + $testSteps .= $this->wrapFunctionCall( + $actor, + $actionObject, + $selector, + $dependentSelector, + $visible + ); break; case "assertEquals": case "assertGreaterOrEquals": @@ -1061,7 +1069,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "expectException": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $assertExpected, $assertActual, $assertMessage, @@ -1076,7 +1084,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $selector, $this->wrapWithDoubleQuotes($attribute), $assertExpected @@ -1093,7 +1101,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "assertTrue": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $assertActual, $assertMessage ); @@ -1101,7 +1109,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "assertArraySubset": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $assertExpected, $assertActual, $assertIsStrict, @@ -1111,7 +1119,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "fail": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $assertMessage ); break; @@ -1119,7 +1127,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - "executeMagentoCLICommand", + $actionObject, $this->wrapWithDoubleQuotes($command) ); $testSteps .= sprintf( @@ -1135,10 +1143,10 @@ private function generateStepsPhp($stepsObject, $hookObject = false) "", $stepKey ) . "Fields['{$fieldKey}'] = ${input};\n"; - $testSteps.= $this->resolveTestVariable($argRef, [$input]); + $testSteps.= $this->resolveTestVariable($argRef, [$input], $actionObject); break; default: - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $input, $parameter); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $input, $parameter); } } @@ -1166,15 +1174,19 @@ private function resolveLocatorFunctionInAttribute($attribute) * * @param string $inputString * @param array $args + * @param ActionObject $actionObject * @return string * @throws \Exception */ - private function resolveTestVariable($inputString, $args) + private function resolveTestVariable($inputString, $args, $actionObject) { $outputString = $inputString; //Loop through each argument, replace and then replace foreach ($args as $arg) { + if ($arg == null) { + continue; + } $outputArg = $arg; // Match on any $$data.key$$ found inside arg, matches[0] will be array of $$data.key$$ preg_match_all("/\\$\\$[\w.\[\]]+\\$\\$/", $outputArg, $matches); @@ -1187,6 +1199,8 @@ private function resolveTestVariable($inputString, $args) //trim "{$variable}" into $variable $outputArg = $this->trimVariableIfNeeded($outputArg); + $outputArg = $this->resolveStepKeyReferences($outputArg, $actionObject->getActionGroupOrigin()); + $outputString = str_replace($arg, $outputArg, $outputString); } @@ -1266,6 +1280,34 @@ private function processQuoteBreaks($match, $argument, $replacement) return $outputArg; } + /** + * Replaces any occurrences of stepKeys in input, if they are found within the given actionGroup. + * Necessary to allow for use of grab/createData actions in actionGroups. + * @param string $input + * @param array $actionGroupOrigin + * @return string + */ + private function resolveStepKeyReferences($input, $actionGroupOrigin) + { + if ($actionGroupOrigin == null) { + return $input; + } + $output = $input; + + $actionGroup = ActionGroupObjectHandler::getInstance()->getObject( + $actionGroupOrigin[ActionGroupObject::ACTION_GROUP_ORIGIN_NAME] + ); + $stepKeys = $actionGroup->extractStepKeys(); + $testInvocationKey = ucfirst($actionGroupOrigin[ActionGroupObject::ACTION_GROUP_ORIGIN_TEST_REF]); + + foreach ($stepKeys as $stepKey) { + if (strpos($output, $stepKey)) { + $output = str_replace($stepKey, $stepKey . $testInvocationKey, $output); + } + } + return $output; + } + /** * Wraps all args inside function give with double quotes. Uses regex to locate arguments of function. * @@ -1537,7 +1579,7 @@ private function addDollarSign($input) private function wrapFunctionCall($actor, $action, ...$args) { $isFirst = true; - $output = sprintf("\t\t$%s->%s(", $actor, $action); + $output = sprintf("\t\t$%s->%s(", $actor, $action->getType()); for ($i = 0; $i < count($args); $i++) { if (null === $args[$i]) { continue; @@ -1552,7 +1594,7 @@ private function wrapFunctionCall($actor, $action, ...$args) $output = $this->resolveEnvReferences($output, $args); - return $this->resolveTestVariable($output, $args); + return $this->resolveTestVariable($output, $args, $action); } /** @@ -1568,7 +1610,7 @@ private function wrapFunctionCall($actor, $action, ...$args) private function wrapFunctionCallWithReturnValue($returnVariable, $actor, $action, ...$args) { $isFirst = true; - $output = sprintf("\t\t$%s = $%s->%s(", $returnVariable, $actor, $action); + $output = sprintf("\t\t$%s = $%s->%s(", $returnVariable, $actor, $action->getType()); for ($i = 0; $i < count($args); $i++) { if (null === $args[$i]) { continue; @@ -1583,7 +1625,7 @@ private function wrapFunctionCallWithReturnValue($returnVariable, $actor, $actio $output = $this->resolveEnvReferences($output, $args); - return $this->resolveTestVariable($output, $args); + return $this->resolveTestVariable($output, $args, $action); } // @codingStandardsIgnoreEnd From 9fb3a47d9927ea9171d87ee1727f0b8486762795 Mon Sep 17 00:00:00 2001 From: KevinBKozan Date: Thu, 8 Mar 2018 14:30:37 -0600 Subject: [PATCH 4/6] MQE-697: Grab test actions's results cannot be used in action-groups - CR fixes. --- .../Util/TestGenerator.php | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 24fa6da02..144616e52 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -385,23 +385,22 @@ private function generateClassAnnotations($annotationType, $annotationName) * statement to handle each unique action. At the bottom of the case statement there is a generic function that can * construct the PHP string for nearly half of all Codeception actions. * - * @param array $stepsObject + * @param array $actionObjects * @param array|bool $hookObject * @return string * @throws TestReferenceException * @throws \Exception * @SuppressWarnings(PHPMD) */ - private function generateStepsPhp($stepsObject, $hookObject = false) + private function generateStepsPhp($actionObjects, $hookObject = false) { //TODO: Refactor Method according to PHPMD warnings, remove @SuppressWarnings accordingly. $testSteps = ""; - foreach ($stepsObject as $steps) { + foreach ($actionObjects as $actionObject) { $actor = "I"; - $actionObject = $steps; - $stepKey = $steps->getStepKey(); - $customActionAttributes = $steps->getCustomActionAttributes(); + $stepKey = $actionObject->getStepKey(); + $customActionAttributes = $actionObject->getCustomActionAttributes(); $attribute = null; $selector = null; $selector1 = null; @@ -1138,13 +1137,13 @@ private function generateStepsPhp($stepsObject, $hookObject = false) ); break; case "field": - $fieldKey = $steps->getCustomActionAttributes()['key']; + $fieldKey = $actionObject->getCustomActionAttributes()['key']; $argRef= "\t\t\$" . str_replace( ucfirst($fieldKey), "", $stepKey ) . "Fields['{$fieldKey}'] = ${input};\n"; - $testSteps.= $this->resolveTestVariable($argRef, [$input], $actionObject); + $testSteps.= $this->resolveTestVariable($argRef, [$input], $actionObject->getActionGroupOrigin()); break; default: $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $input, $parameter); @@ -1179,7 +1178,7 @@ private function resolveLocatorFunctionInAttribute($attribute) * @return string * @throws \Exception */ - private function resolveTestVariable($inputString, $args, $actionObject) + private function resolveTestVariable($inputString, $args, $actionOrigin) { $outputString = $inputString; @@ -1200,7 +1199,7 @@ private function resolveTestVariable($inputString, $args, $actionObject) //trim "{$variable}" into $variable $outputArg = $this->trimVariableIfNeeded($outputArg); - $outputArg = $this->resolveStepKeyReferences($outputArg, $actionObject->getActionGroupOrigin()); + $outputArg = $this->resolveStepKeyReferences($outputArg, $actionOrigin); $outputString = str_replace($arg, $outputArg, $outputString); } @@ -1572,7 +1571,7 @@ private function addDollarSign($input) * Wrap parameters into a function call. * * @param string $actor - * @param string $action + * @param actionObject $action * @param array ...$args * @return string * @throws \Exception @@ -1595,7 +1594,7 @@ private function wrapFunctionCall($actor, $action, ...$args) $output = $this->resolveEnvReferences($output, $args); - return $this->resolveTestVariable($output, $args, $action); + return $this->resolveTestVariable($output, $args, $action->getActionGroupOrigin()); } /** @@ -1626,7 +1625,7 @@ private function wrapFunctionCallWithReturnValue($returnVariable, $actor, $actio $output = $this->resolveEnvReferences($output, $args); - return $this->resolveTestVariable($output, $args, $action); + return $this->resolveTestVariable($output, $args, $action->getActionGroupOrigin()); } // @codingStandardsIgnoreEnd From 02125db3d89d635dde4b39a710a1df48695f6748 Mon Sep 17 00:00:00 2001 From: KevinBKozan Date: Fri, 9 Mar 2018 15:08:50 -0600 Subject: [PATCH 5/6] MQE-697: Grab test actions's results cannot be used in action-groups - renaming actionGroupOrigin to actionOrigin. --- .../Test/Objects/ActionObject.php | 16 ++++++++-------- .../Util/TestGenerator.php | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index fcc42be55..a41b2f981 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -85,11 +85,11 @@ class ActionObject private $timeout; /** - * Array with two items, if this actionObject was created as the result of an actionGroup call: + * An array with items containing information of the origin of this action. * * @var array */ - private $actionGroupOrigin = []; + private $actionOrigin = []; /** * ActionObject constructor. @@ -99,7 +99,7 @@ class ActionObject * @param array $actionAttributes * @param string|null $linkedAction * @param string $order - * @param array $actionGroupOrigin + * @param array $actionOrigin */ public function __construct( $stepKey, @@ -107,13 +107,13 @@ public function __construct( $actionAttributes, $linkedAction = null, $order = ActionObject::MERGE_ACTION_ORDER_BEFORE, - $actionGroupOrigin = null + $actionOrigin = null ) { $this->stepKey = $stepKey; $this->type = $type; $this->actionAttributes = $actionAttributes; $this->linkedAction = $linkedAction; - $this->actionGroupOrigin = $actionGroupOrigin; + $this->actionOrigin = $actionOrigin; if ($order == ActionObject::MERGE_ACTION_ORDER_AFTER) { $this->orderOffset = 1; @@ -141,13 +141,13 @@ public function getType() } /** - * Getter for actionGroupOrigin + * Getter for actionOrigin * * @return string */ - public function getActionGroupOrigin() + public function getActionOrigin() { - return $this->actionGroupOrigin; + return $this->actionOrigin; } /** diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 144616e52..3aa4fa1b2 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -1594,7 +1594,7 @@ private function wrapFunctionCall($actor, $action, ...$args) $output = $this->resolveEnvReferences($output, $args); - return $this->resolveTestVariable($output, $args, $action->getActionGroupOrigin()); + return $this->resolveTestVariable($output, $args, $action->getActionOrigin()); } /** @@ -1625,7 +1625,7 @@ private function wrapFunctionCallWithReturnValue($returnVariable, $actor, $actio $output = $this->resolveEnvReferences($output, $args); - return $this->resolveTestVariable($output, $args, $action->getActionGroupOrigin()); + return $this->resolveTestVariable($output, $args, $action->getActionOrigin()); } // @codingStandardsIgnoreEnd From 87dfe87561c2438218375c47f57351f3c6509da0 Mon Sep 17 00:00:00 2001 From: KevinBKozan Date: Mon, 12 Mar 2018 08:38:07 -0500 Subject: [PATCH 6/6] MQE-697: Grab test actions's results cannot be used in action-groups - static/verification test fixes. --- src/Magento/FunctionalTestingFramework/Util/TestGenerator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 3aa4fa1b2..ab0e19874 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -1143,7 +1143,7 @@ private function generateStepsPhp($actionObjects, $hookObject = false) "", $stepKey ) . "Fields['{$fieldKey}'] = ${input};\n"; - $testSteps.= $this->resolveTestVariable($argRef, [$input], $actionObject->getActionGroupOrigin()); + $testSteps.= $this->resolveTestVariable($argRef, [$input], $actionObject->getActionOrigin()); break; default: $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $input, $parameter); @@ -1174,7 +1174,7 @@ private function resolveLocatorFunctionInAttribute($attribute) * * @param string $inputString * @param array $args - * @param ActionObject $actionObject + * @param array $actionOrigin * @return string * @throws \Exception */