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 new file mode 100644 index 000000000..8a56a6906 --- /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/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/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..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 @@ -153,12 +156,14 @@ private function getResolvedActionsWithArgs($arguments, $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(), array_merge($action->getCustomActionAttributes(), $newActionAttributes), - $action->getLinkedAction() == null ? null : $action->getLinkedAction() . $actionReferenceKey, - $action->getOrderOffset() + $action->getLinkedAction() == null ? null : $action->getLinkedAction() . ucfirst($actionReferenceKey), + $action->getOrderOffset(), + [self::ACTION_GROUP_ORIGIN_NAME => $this->name, + self::ACTION_GROUP_ORIGIN_TEST_REF => $actionReferenceKey] ); } @@ -307,6 +312,19 @@ private function replacePersistedArgument($replacement, $attributeValue, $fullVa return $newAttributeValue; } + /** + * Finds and returns all original stepkeys of actions in actionGroup. + * @return string[] + */ + public function extractStepKeys() + { + $originalKeys = []; + foreach ($this->parsedActions as $action) { + $originalKeys[] = $action->getStepKey(); + } + return $originalKeys; + } + /** * 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..a41b2f981 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; + /** + * An array with items containing information of the origin of this action. + * + * @var array + */ + private $actionOrigin = []; + /** * ActionObject constructor. * @@ -92,18 +99,21 @@ class ActionObject * @param array $actionAttributes * @param string|null $linkedAction * @param string $order + * @param array $actionOrigin */ public function __construct( $stepKey, $type, $actionAttributes, $linkedAction = null, - $order = ActionObject::MERGE_ACTION_ORDER_BEFORE + $order = ActionObject::MERGE_ACTION_ORDER_BEFORE, + $actionOrigin = null ) { $this->stepKey = $stepKey; $this->type = $type; $this->actionAttributes = $actionAttributes; $this->linkedAction = $linkedAction; + $this->actionOrigin = $actionOrigin; if ($order == ActionObject::MERGE_ACTION_ORDER_AFTER) { $this->orderOffset = 1; @@ -130,6 +140,16 @@ public function getType() return $this->type; } + /** + * Getter for actionOrigin + * + * @return string + */ + public function getActionOrigin() + { + return $this->actionOrigin; + } + /** * 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 2e14df761..ab0e19874 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; @@ -383,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"; - $actionName = $steps->getType(); - $stepKey = $steps->getStepKey(); - $customActionAttributes = $steps->getCustomActionAttributes(); + $stepKey = $actionObject->getStepKey(); + $customActionAttributes = $actionObject->getCustomActionAttributes(); $attribute = null; $selector = null; $selector1 = null; @@ -434,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']; @@ -491,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']); @@ -580,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 @@ -808,7 +809,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "assertArrayIsSorted": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $parameterArray, $this->wrapWithDoubleQuotes($sortOrder) ); @@ -826,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": @@ -839,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 ); @@ -861,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; @@ -885,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, @@ -908,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 ); @@ -930,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": @@ -954,7 +955,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - $actionName, + $actionObject, $selector, $input ); @@ -964,7 +965,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - $actionName, + $actionObject, $selector ); break; @@ -972,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, @@ -990,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, @@ -1017,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 @@ -1032,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": @@ -1062,7 +1069,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "expectException": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $assertExpected, $assertActual, $assertMessage, @@ -1077,7 +1084,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $selector, $this->wrapWithDoubleQuotes($attribute), $assertExpected @@ -1094,7 +1101,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "assertTrue": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $assertActual, $assertMessage ); @@ -1102,7 +1109,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "assertArraySubset": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $assertExpected, $assertActual, $assertIsStrict, @@ -1112,7 +1119,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) case "fail": $testSteps .= $this->wrapFunctionCall( $actor, - $actionName, + $actionObject, $assertMessage ); break; @@ -1120,7 +1127,7 @@ private function generateStepsPhp($stepsObject, $hookObject = false) $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - "executeMagentoCLICommand", + $actionObject, $this->wrapWithDoubleQuotes($command) ); $testSteps .= sprintf( @@ -1130,16 +1137,16 @@ 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]); + $testSteps.= $this->resolveTestVariable($argRef, [$input], $actionObject->getActionOrigin()); break; default: - $testSteps .= $this->wrapFunctionCall($actor, $actionName, $selector, $input, $parameter); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $input, $parameter); } } @@ -1167,15 +1174,19 @@ private function resolveLocatorFunctionInAttribute($attribute) * * @param string $inputString * @param array $args + * @param array $actionOrigin * @return string * @throws \Exception */ - private function resolveTestVariable($inputString, $args) + private function resolveTestVariable($inputString, $args, $actionOrigin) { $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); @@ -1188,6 +1199,8 @@ private function resolveTestVariable($inputString, $args) //trim "{$variable}" into $variable $outputArg = $this->trimVariableIfNeeded($outputArg); + $outputArg = $this->resolveStepKeyReferences($outputArg, $actionOrigin); + $outputString = str_replace($arg, $outputArg, $outputString); } @@ -1267,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. * @@ -1530,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 @@ -1538,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; @@ -1553,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->getActionOrigin()); } /** @@ -1569,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; @@ -1584,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->getActionOrigin()); } // @codingStandardsIgnoreEnd