diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php
index f9fc3346c..bf5eb92e2 100644
--- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php
+++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php
@@ -14,6 +14,7 @@
use Magento\FunctionalTestingFramework\Page\Objects\SectionObject;
use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject;
use Magento\FunctionalTestingFramework\Test\Objects\ActionObject;
+use Magento\FunctionalTestingFramework\Test\Objects\ArgumentObject;
use PHPUnit\Framework\TestCase;
use tests\unit\Util\ActionGroupObjectBuilder;
use tests\unit\Util\EntityDataObjectBuilder;
@@ -49,10 +50,29 @@ public function testGetStepsWithCustomArgs()
$actionGroupUnderTest = (new ActionGroupObjectBuilder())
->withActionObjects([new ActionObject('action1', 'testAction', ['userInput' => '{{arg1.field2}}'])])
+ ->withArguments([new ArgumentObject('arg1', null, 'entity')])
->build();
$steps = $actionGroupUnderTest->getSteps(['arg1' => 'data2'], self::ACTION_GROUP_MERGE_KEY);
$this->assertOnMergeKeyAndActionValue($steps, ['userInput' => 'testValue2']);
+
+ // entity.field as argument
+ $actionGroupUnderTest = (new ActionGroupObjectBuilder())
+ ->withActionObjects([new ActionObject('action1', 'testAction', ['userInput' => '{{arg1}}'])])
+ ->withArguments([new ArgumentObject('arg1', null, 'entity')])
+ ->build();
+
+ $steps = $actionGroupUnderTest->getSteps(['arg1' => 'data2.field2'], self::ACTION_GROUP_MERGE_KEY);
+ $this->assertOnMergeKeyAndActionValue($steps, ['userInput' => 'testValue2']);
+
+ // String Data
+ $actionGroupUnderTest = (new ActionGroupObjectBuilder())
+ ->withActionObjects([new ActionObject('action1', 'testAction', ['userInput' => '{{simple}}'])])
+ ->withArguments([new ArgumentObject('simple', null, 'string')])
+ ->build();
+
+ $steps = $actionGroupUnderTest->getSteps(['simple' => 'override'], self::ACTION_GROUP_MERGE_KEY);
+ $this->assertOnMergeKeyAndActionValue($steps, ['userInput' => 'override']);
}
/**
@@ -62,10 +82,20 @@ public function testGetStepsWithPersistedArgs()
{
$actionGroupUnderTest = (new ActionGroupObjectBuilder())
->withActionObjects([new ActionObject('action1', 'testAction', ['userInput' => '{{arg1.field2}}'])])
+ ->withArguments([new ArgumentObject('arg1', null, 'entity')])
->build();
$steps = $actionGroupUnderTest->getSteps(['arg1' => '$data3$'], self::ACTION_GROUP_MERGE_KEY);
$this->assertOnMergeKeyAndActionValue($steps, ['userInput' => '$data3.field2$']);
+
+ // Simple Data
+ $actionGroupUnderTest = (new ActionGroupObjectBuilder())
+ ->withActionObjects([new ActionObject('action1', 'testAction', ['userInput' => '{{simple}}'])])
+ ->withArguments([new ArgumentObject('simple', null, 'string')])
+ ->build();
+
+ $steps = $actionGroupUnderTest->getSteps(['simple' => '$data3.field2$'], self::ACTION_GROUP_MERGE_KEY);
+ $this->assertOnMergeKeyAndActionValue($steps, ['userInput' => '$data3.field2$']);
}
/**
@@ -81,6 +111,7 @@ public function testGetStepsWithNoFieldArg()
$actionGroupUnderTest = (new ActionGroupObjectBuilder())
->withActionObjects([new ActionObject('action1', 'testAction', ['userInput' => '{{arg1}}'])])
+ ->withArguments([new ArgumentObject('arg1', null, 'entity')])
->build();
$steps = $actionGroupUnderTest->getSteps(['arg1' => 'data2.field2'], self::ACTION_GROUP_MERGE_KEY);
@@ -111,6 +142,12 @@ public function testGetStepsWithNoArgs()
*/
public function testGetStepsWithParameterizedArg()
{
+ // Mock Entity Object Handler
+ $this->setEntityObjectHandlerReturn(function ($entityName) {
+ if ($entityName == "data2") {
+ return (new EntityDataObjectBuilder())->withDataFields(['field2' => 'testValue2'])->build();
+ }
+ });
// mock the section object handler response
$element = new ElementObject("element1", "textArea", ".selector {{var1}}", null, null, true);
$section = new SectionObject("testSection", ["element1" => $element]);
@@ -120,11 +157,55 @@ public function testGetStepsWithParameterizedArg()
$actionGroupUnderTest = (new ActionGroupObjectBuilder())
->withActionObjects(
- [new ActionObject('action1', 'testAction', ['selector' => '{{section1.element1(arg1.field1)}}'])]
+ [new ActionObject('action1', 'testAction', ['selector' => '{{section1.element1(arg1.field2)}}'])]
)
+ ->withArguments([new ArgumentObject('arg1', null, 'entity')])
->build();
- $steps = $actionGroupUnderTest->getSteps(['arg1' => '$someData$'], self::ACTION_GROUP_MERGE_KEY);
+ // XML Data
+ $steps = $actionGroupUnderTest->getSteps(['arg1' => 'data2'], self::ACTION_GROUP_MERGE_KEY);
+ $this->assertOnMergeKeyAndActionValue($steps, ['selector' => '.selector testValue2']);
+
+ // Persisted Data
+ $steps = $actionGroupUnderTest->getSteps(['arg1' => '$data2$'], self::ACTION_GROUP_MERGE_KEY);
+ $this->assertOnMergeKeyAndActionValue($steps, ['selector' => '.selector $data2.field2$']);
+ }
+
+ /**
+ * Tests a parameterized section reference in an action group resolved with user simpleArgs.
+ */
+ public function testGetStepsWithParameterizedSimpleArg()
+ {
+ // Mock Entity Object Handler
+ $this->setEntityObjectHandlerReturn(function ($entityName) {
+ if ($entityName == "data2") {
+ return (new EntityDataObjectBuilder())->withDataFields(['field2' => 'testValue2'])->build();
+ }
+ });
+ // mock the section object handler response
+ $element = new ElementObject("element1", "textArea", ".selector {{var1}}", null, null, true);
+ $section = new SectionObject("testSection", ["element1" => $element]);
+ // bypass the private constructor
+ $sectionInstance = AspectMock::double(SectionObjectHandler::class, ['getObject' => $section])->make();
+ AspectMock::double(SectionObjectHandler::class, ['getInstance' => $sectionInstance]);
+
+ $actionGroupUnderTest = (new ActionGroupObjectBuilder())
+ ->withActionObjects(
+ [new ActionObject('action1', 'testAction', ['selector' => '{{section1.element1(simple)}}'])]
+ )
+ ->withArguments([new ArgumentObject('simple', null, 'string')])
+ ->build();
+
+ // String Literal
+ $steps = $actionGroupUnderTest->getSteps(['simple' => 'stringLiteral'], self::ACTION_GROUP_MERGE_KEY);
+ $this->assertOnMergeKeyAndActionValue($steps, ['selector' => '.selector stringLiteral']);
+
+ // String Literal w/ data-like structure
+ $steps = $actionGroupUnderTest->getSteps(['simple' => 'data2.field2'], self::ACTION_GROUP_MERGE_KEY);
+ $this->assertOnMergeKeyAndActionValue($steps, ['selector' => '.selector data2.field2']);
+
+ // Persisted Data
+ $steps = $actionGroupUnderTest->getSteps(['simple' => '$someData.field1$'], self::ACTION_GROUP_MERGE_KEY);
$this->assertOnMergeKeyAndActionValue($steps, ['selector' => '.selector $someData.field1$']);
}
@@ -135,6 +216,7 @@ public function testGetStepsWithOuterScopePersistence()
{
$actionGroupUnderTest = (new ActionGroupObjectBuilder())
->withActionObjects([new ActionObject('action1', 'testAction', ['userInput' => '{{arg1.field1}}'])])
+ ->withArguments([new ArgumentObject('arg1', null, 'entity')])
->build();
$steps = $actionGroupUnderTest->getSteps(['arg1' => '$$someData$$'], self::ACTION_GROUP_MERGE_KEY);
@@ -147,11 +229,11 @@ public function testGetStepsWithOuterScopePersistence()
public function testExceptionOnMissingActions()
{
$actionGroupUnderTest = (new ActionGroupObjectBuilder())
- ->withArguments(['arg1' => null])
+ ->withArguments([new ArgumentObject('arg1', null, 'entity')])
->build();
$this->expectException(TestReferenceException::class);
- $this->expectExceptionMessageRegExp('/Argument\(s\) missed .* for actionGroup/');
+ $this->expectExceptionMessageRegExp('/Arguments missed .* for actionGroup/');
$actionGroupUnderTest->getSteps(['arg2' => 'data1'], self::ACTION_GROUP_MERGE_KEY);
}
@@ -161,11 +243,11 @@ public function testExceptionOnMissingActions()
public function testExceptionOnMissingArguments()
{
$actionGroupUnderTest = (new ActionGroupObjectBuilder())
- ->withArguments(['arg1' => null])
+ ->withArguments([new ArgumentObject('arg1', null, 'entity')])
->build();
$this->expectException(TestReferenceException::class);
- $this->expectExceptionMessageRegExp('/Not enough arguments given for actionGroup .*/');
+ $this->expectExceptionMessageRegExp('/Arguments missed .* for actionGroup/');
$actionGroupUnderTest->getSteps(null, self::ACTION_GROUP_MERGE_KEY);
}
diff --git a/dev/tests/unit/Util/ActionGroupObjectBuilder.php b/dev/tests/unit/Util/ActionGroupObjectBuilder.php
index aa2346e0b..4844776d5 100644
--- a/dev/tests/unit/Util/ActionGroupObjectBuilder.php
+++ b/dev/tests/unit/Util/ActionGroupObjectBuilder.php
@@ -28,11 +28,11 @@ class ActionGroupObjectBuilder
private $actionObjects = [];
/**
- * Action Group Object Builder default arguments.
+ * Action Group Object Builder default entity arguments.
*
* @var array
*/
- private $arguments = ['arg1' => 'data1'];
+ private $arguments = [];
/**
* Setter for the Action Group Object name
diff --git a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt
new file mode 100644
index 000000000..37c9977ed
--- /dev/null
+++ b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt
@@ -0,0 +1,34 @@
+see("stringLiteral", "#element .stringLiteral");
+ }
+}
diff --git a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt
new file mode 100644
index 000000000..4c8e14cf9
--- /dev/null
+++ b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt
@@ -0,0 +1,41 @@
+see("overrideString", "#element .overrideString");
+ $I->see("1", "#element .1");
+ $I->see("1.5", "#element .1.5");
+ $I->see("true", "#element .true");
+ $I->see("simpleData.firstname", "#element .simpleData.firstname");
+ $I->see($persisted->getCreatedDataByName('data'), "#element ." . $persisted->getCreatedDataByName('data'));
+ $I->see("John", "#element .John");
+ $I->see($simpleData->getCreatedDataByName('firstname'), "#element ." . $simpleData->getCreatedDataByName('firstname'));
+ }
+}
diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml
index a06ac7967..1fec39772 100644
--- a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml
+++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml
@@ -34,4 +34,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml
index 05c9a669e..1918852f1 100644
--- a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml
+++ b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml
@@ -63,4 +63,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/verification/Tests/ActionGroupGenerationTest.php b/dev/tests/verification/Tests/ActionGroupGenerationTest.php
index e75fe43d0..3af62eb77 100644
--- a/dev/tests/verification/Tests/ActionGroupGenerationTest.php
+++ b/dev/tests/verification/Tests/ActionGroupGenerationTest.php
@@ -74,4 +74,26 @@ public function testActionGroupWithMultipleParameterSelectorsFromDefaultArgument
{
$this->generateAndCompareTest('ActionGroupWithMultipleParameterSelectorsFromDefaultArgument');
}
+
+ /**
+ * Test generation of a test referencing an action group with simple passed data.
+ *
+ * @throws \Exception
+ * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException
+ */
+ public function testActionGroupWithSimpleDataUsageFromPassedArgument()
+ {
+ $this->generateAndCompareTest('ActionGroupWithSimpleDataUsageFromPassedArgument');
+ }
+
+ /**
+ * Test generation of a test referencing an action group with default data.
+ *
+ * @throws \Exception
+ * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException
+ */
+ public function testActionGroupWithSimpleDataUsageFromDefaultArgument()
+ {
+ $this->generateAndCompareTest('ActionGroupWithSimpleDataUsageFromDefaultArgument');
+ }
}
diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php
index 7cb21465f..7868cbfc3 100644
--- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php
+++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php
@@ -7,6 +7,7 @@
namespace Magento\FunctionalTestingFramework\Test\Objects;
use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException;
+use Magento\FunctionalTestingFramework\Test\Util\ActionGroupObjectExtractor;
use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil;
/**
@@ -35,7 +36,7 @@ class ActionGroupObject
private $parsedActions = [];
/**
- * An array used to store the default entities if the user does not specify any
+ * An array used to store argument names to values
*
* @var array
*/
@@ -45,7 +46,7 @@ class ActionGroupObject
* ActionGroupObject constructor.
*
* @param string $name
- * @param string $arguments
+ * @param ArgumentObject[] $arguments
* @param array $actions
*/
public function __construct($name, $arguments, $actions)
@@ -71,23 +72,42 @@ public function __construct($name, $arguments, $actions)
public function getSteps($arguments, $actionReferenceKey)
{
$mergeUtil = new ActionMergeUtil($this->name, "ActionGroup");
- $args = $this->arguments;
- $emptyArguments = array_keys($args, null, true);
- if (!empty($emptyArguments) && $arguments !== null) {
- $diff = array_diff($emptyArguments, array_keys($arguments));
- if (!empty($diff)) {
- $error = 'Argument(s) missed (' . implode(", ", $diff) . ') for actionGroup "' . $this->name . '"';
- throw new TestReferenceException($error);
+
+ $args = $this->resolveArguments($arguments);
+
+ return $mergeUtil->resolveActionSteps($this->getResolvedActionsWithArgs($args, $actionReferenceKey), true);
+ }
+
+ /**
+ * Iterates through given $arguments and overrides ActionGroup's argument values, if any are found.
+ * @param array $arguments
+ * @return ArgumentObject[]
+ */
+ private function resolveArguments($arguments)
+ {
+ $resolvedArgumentList = [];
+ $emptyArguments = [];
+
+ foreach ($this->arguments as $argumentObj) {
+ if ($arguments !== null && array_key_exists($argumentObj->getName(), $arguments)) {
+ $resolvedArgumentList[] = new ArgumentObject(
+ $argumentObj->getName(),
+ $arguments[$argumentObj->getName()],
+ $argumentObj->getDataType()
+ );
+ } elseif ($argumentObj->getValue() === null) {
+ $emptyArguments[] = $argumentObj->getName();
+ } else {
+ $resolvedArgumentList[] = $argumentObj;
}
- } elseif (!empty($emptyArguments)) {
- $error = 'Not enough arguments given for actionGroup "' . $this->name . '"';
- throw new TestReferenceException($error);
}
- if ($arguments) {
- $args = array_merge($args, $arguments);
+
+ if (!empty($emptyArguments)) {
+ $error = 'Arguments missed (' . implode(", ", $emptyArguments) . ') for actionGroup "' . $this->name . '"';
+ throw new TestReferenceException($error);
}
- return $mergeUtil->resolveActionSteps($this->getResolvedActionsWithArgs($args, $actionReferenceKey), true);
+ return $resolvedArgumentList;
}
/**
@@ -199,17 +219,27 @@ private function replaceAttributeArgumentInVariable(
// Check if arguments has a mapping for the given variableName
if ($variableName === false) {
- $variableName = $variable;
+ $variableName = trim($variable, "'");
}
- if (!array_key_exists($variableName, $arguments)) {
+ $matchedArgument = $this->findArgumentByName($variableName, $arguments);
+ if ($matchedArgument === null) {
return $attributeValue;
}
- $isPersisted = strstr($arguments[$variableName], '$');
+ if ($matchedArgument->getDataType() === ArgumentObject::ARGUMENT_DATA_STRING) {
+ return $this->replaceSimpleArgument(
+ $matchedArgument->getResolvedValue($isInnerArgument),
+ $variableName,
+ $attributeValue,
+ $isInnerArgument
+ );
+ }
+
+ $isPersisted = preg_match('/\$[\w.]+\$/', $matchedArgument->getResolvedValue($isInnerArgument));
if ($isPersisted) {
return $this->replacePersistedArgument(
- $arguments[$variableName],
+ $matchedArgument->getResolvedValue($isInnerArgument),
$attributeValue,
$variable,
$variableName,
@@ -218,7 +248,29 @@ private function replaceAttributeArgumentInVariable(
}
//replace argument ONLY when there is no letters attached before after (ex. category.name vs categoryTreeButton)
- return preg_replace("/(?getResolvedValue($isInnerArgument),
+ $attributeValue
+ );
+ }
+
+ /**
+ * Replaces any arguments that were declared as simpleData="true".
+ * Takes in isInnerArgument to determine what kind of replacement to expect: {{data}} vs section.element(data)
+ * @param string $argumentValue
+ * @param string $variableName
+ * @param string $attributeValue
+ * @param boolean $isInnerArgument
+ * @return string
+ */
+ private function replaceSimpleArgument($argumentValue, $variableName, $attributeValue, $isInnerArgument)
+ {
+ if ($isInnerArgument) {
+ return preg_replace("/(?getName() == $name;
+ }
+ );
+ if (isset(array_values($matchedArgument)[0])) {
+ return array_values($matchedArgument)[0];
+ }
+ return null;
+ }
}
diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ArgumentObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ArgumentObject.php
new file mode 100644
index 000000000..c829e66b3
--- /dev/null
+++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ArgumentObject.php
@@ -0,0 +1,122 @@
+name = $name;
+ $this->value = $value;
+ $this->dataType = $dataType;
+ }
+
+ /**
+ * Function to return string property name.
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Function to return string property value.
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Function to return string property dataType.
+ * @return string
+ */
+ public function getDataType()
+ {
+ return $this->dataType;
+ }
+
+ /**
+ * Override's private string property value.
+ * @param string $value
+ * @return void
+ */
+ public function overrideValue($value)
+ {
+ $this->value = $value;
+ }
+
+ /**
+ * Returns the resolved value that the argument needs to have, depending on scope of where argument is referenced.
+ * @param boolean $isInnerArgument
+ * @return string
+ */
+ public function getResolvedValue($isInnerArgument)
+ {
+ if ($this->dataType === ArgumentObject::ARGUMENT_DATA_ENTITY) {
+ return $this->value;
+ } else {
+ return $this->resolveStringArgument($isInnerArgument);
+ }
+ }
+
+ /**
+ * Resolves simple string arguments and returns the appropriate format for simple replacement.
+ * Takes in boolean to determine if the replacement is being done with an inner argument (as in if it's a parameter)
+ *
+ * Example Type Non Inner Inner
+ * {{XML.DATA}}: {{XML.DATA}} XML.DATA
+ * $TEST.DATA$: $TEST.DATA$ $TEST.DATA$
+ * stringLiteral stringLiteral 'stringLiteral'
+ *
+ * @param boolean $isInnerArgument
+ * @return string
+ */
+ private function resolveStringArgument($isInnerArgument)
+ {
+ if ($isInnerArgument) {
+ return "'" . $this->value . "'";
+ } else {
+ return $this->value;
+ }
+ }
+}
diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php
index 4f2b78174..a49246d44 100644
--- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php
+++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php
@@ -6,7 +6,9 @@
namespace Magento\FunctionalTestingFramework\Test\Util;
+use Magento\FunctionalTestingFramework\Data\Argument\Interpreter\Argument;
use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject;
+use Magento\FunctionalTestingFramework\Test\Objects\ArgumentObject;
/**
* Class ActionGroupObjectExtractor
@@ -77,9 +79,12 @@ private function extractArguments($arguments)
);
foreach ($argData as $argName => $argValue) {
- $parsedArguments[$argName] = $argValue[self::DEFAULT_VALUE] ?? null;
+ $parsedArguments[] = new ArgumentObject(
+ $argValue[ArgumentObject::ARGUMENT_NAME],
+ $argValue[ArgumentObject::ARGUMENT_DEFAULT_VALUE] ?? null,
+ $argValue[ArgumentObject::ARGUMENT_DATA_TYPE] ?? ArgumentObject::ARGUMENT_DATA_ENTITY
+ );
}
-
return $parsedArguments;
}
}
diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd
index a92569098..5c5fc0059 100644
--- a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd
+++ b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd
@@ -24,6 +24,7 @@
+
@@ -32,4 +33,10 @@
+
+
+
+
+
+