diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d8a662fe..04999e2c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
Magento Functional Testing Framework Changelog
================================================
+3.8.0
+---------
+
+### Updates:
+* Allow MFTF Helpers to Return Data to MFTF Test
+* Improve parallel grouping and fix an issue with unbalanced groups
+* Added new action WaitForElementClickable
+
3.7.3
---------
diff --git a/composer.json b/composer.json
index 8fedf25a8..9a7757c5d 100755
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
"name": "magento/magento2-functional-testing-framework",
"description": "Magento2 Functional Testing Framework",
"type": "library",
- "version": "3.7.3",
+ "version": "3.8.0",
"license": "AGPL-3.0",
"keywords": ["magento", "automation", "functional", "testing"],
"config": {
diff --git a/composer.lock b/composer.lock
index 4a1a7d2be..8000882be 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "822c40666da3ff087f25393fd4dc9371",
+ "content-hash": "35ff8c71326b9f8ab0885c8b55dd59cf",
"packages": [
{
"name": "allure-framework/allure-codeception",
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Helper/CustomHelper.php b/dev/tests/functional/tests/MFTF/DevDocs/Helper/CustomHelper.php
index 46fba18d9..3705ec1d0 100644
--- a/dev/tests/functional/tests/MFTF/DevDocs/Helper/CustomHelper.php
+++ b/dev/tests/functional/tests/MFTF/DevDocs/Helper/CustomHelper.php
@@ -46,4 +46,15 @@ public function goTo(
print('$bla = ' . $bla . PHP_EOL);
print('array $arraysomething = [' . implode(', ', $arraysomething) . ']' . PHP_EOL);
}
+
+ /**
+ * Returns value of provided param $text
+ *
+ * @param string $text
+ * @return string
+ */
+ public function getText(string $text): string
+ {
+ return $text;
+ }
}
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml
index bf074d516..911bc65eb 100644
--- a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml
+++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml
@@ -42,6 +42,14 @@
987
+
+ some text
+
+
+ some text
+ getText
+
+
diff --git a/dev/tests/verification/Resources/DataActionsTest.txt b/dev/tests/verification/Resources/DataActionsTest.txt
index f84f97040..178c579da 100644
--- a/dev/tests/verification/Resources/DataActionsTest.txt
+++ b/dev/tests/verification/Resources/DataActionsTest.txt
@@ -53,6 +53,7 @@ class DataActionsTestCest
*/
public function DataActionsTest(AcceptanceTester $I)
{
+ $I->waitForElementClickable(".functionalTestSelector"); // stepKey: waitForElementClickable
$I->createEntity("createdInTest", "test", "entity", [], []); // stepKey: createdInTest
$I->updateEntity("createdInTest", "test", "entity",[]); // stepKey: updateInTest
$I->deleteEntity("createdInTest", "test"); // stepKey: deleteInTest
diff --git a/dev/tests/verification/TestModule/Test/DataActionsTest.xml b/dev/tests/verification/TestModule/Test/DataActionsTest.xml
index b75bc98f8..2575c41b0 100644
--- a/dev/tests/verification/TestModule/Test/DataActionsTest.xml
+++ b/dev/tests/verification/TestModule/Test/DataActionsTest.xml
@@ -13,8 +13,9 @@
-
+
+
diff --git a/docs/test/actions.md b/docs/test/actions.md
index 42ecde053..373a44ee0 100644
--- a/docs/test/actions.md
+++ b/docs/test/actions.md
@@ -2374,10 +2374,28 @@ Attribute|Type|Use|Description
#### Example
```xml
-
```
+### waitForElementClickable
+
+See [waitForElementClickable docs on codeception.com](http://codeception.com/docs/modules/WebDriver#waitForElementClickable).
+
+Attribute|Type|Use|Description
+---|---|---|---
+`selector`|string|optional| The selector identifying the corresponding HTML element.
+`time`|string|optional| The number of seconds to wait for the element to appear.
+`stepKey`|string|required| A unique identifier of the action.
+`before`|string|optional| `stepKey` of action that must be executed next.
+`after`|string|optional| `stepKey` of preceding action.
+
+#### Example
+
+```xml
+
+
+```
+
### waitForJS
See [waitForJS docs on codeception.com](http://codeception.com/docs/modules/WebDriver#waitForJS).
diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/TestObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/TestObject.php
index 8341fc7b1..f556947f1 100644
--- a/src/Magento/FunctionalTestingFramework/Test/Objects/TestObject.php
+++ b/src/Magento/FunctionalTestingFramework/Test/Objects/TestObject.php
@@ -21,14 +21,35 @@ class TestObject
const TEST_ACTION_WEIGHT = [
'waitForPageLoad' => 1500,
- 'amOnPage' => 1000,
+ 'amOnPage' => 1500,
'waitForLoadingMaskToDisappear' => 500,
'wait' => self::WAIT_TIME_ATTRIBUTE,
+ 'waitForAjaxLoad' => 500,
+ 'waitForElementNotVisible' => 500,
+ 'waitForElementVisible' => 500,
+ 'waitForText' => 500,
+ 'waitForElement' => 500,
+ 'waitForJS' => 500,
'comment' => 5,
'assertCount' => 5,
- 'closeAdminNotification' => 10
+ 'closeAdminNotification' => 10,
+ 'magentoCLI' => 1000,
+ 'magentoCron' => 3000,
+ 'createData' => 500,
+ 'deleteData' => 200,
+ 'updateData' => 200,
+ 'getOTP' => 1000,
];
+ const WEBAPI_AUTH_TEST_ACTIONS = [
+ 'createData',
+ 'deleteData',
+ 'updateData',
+ 'getData',
+ ];
+
+ const WEBAPI_AUTH_TEST_ACTION_WEIGHT = 6000;
+
/**
* Name of the test
*
@@ -85,6 +106,13 @@ class TestObject
*/
private $deprecated;
+ /**
+ * Indicates if a test contains an action that requires Web API authentication.
+ *
+ * @var boolean
+ */
+ private $hasWebApiAuthAction;
+
/**
* TestObject constructor.
*
@@ -112,6 +140,7 @@ public function __construct(
$this->filename = $filename;
$this->parentTest = $parentTest;
$this->deprecated = $deprecated;
+ $this->hasWebApiAuthAction = false;
}
/**
@@ -222,7 +251,11 @@ public function getEstimatedDuration()
$testTime = $this->calculateWeightedActionTimes($this->getOrderedActions());
- return $hookTime + $testTime;
+ if ($this->hasWebApiAuthAction) {
+ return $hookTime + $testTime + self::WEBAPI_AUTH_TEST_ACTION_WEIGHT;
+ } else {
+ return $hookTime + $testTime;
+ }
}
/**
@@ -237,6 +270,11 @@ private function calculateWeightedActionTimes($actions)
// search for any actions of special type
foreach ($actions as $action) {
/** @var ActionObject $action */
+
+ if (!$this->hasWebApiAuthAction && in_array($action->getType(), self::WEBAPI_AUTH_TEST_ACTIONS)) {
+ $this->hasWebApiAuthAction = true;
+ }
+
if (array_key_exists($action->getType(), self::TEST_ACTION_WEIGHT)) {
$weight = self::TEST_ACTION_WEIGHT[$action->getType()];
if ($weight === self::WAIT_TIME_ATTRIBUTE) {
diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/waitActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/waitActions.xsd
index 70b8201a1..18214ba9a 100644
--- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/waitActions.xsd
+++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/waitActions.xsd
@@ -23,6 +23,8 @@
+
+
@@ -224,4 +226,19 @@
+
+
+
+ Waits up to $timeout seconds for the given element to be clickable.
+ If element doesn’t become clickable, a timeout exception is thrown.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
index c0249a32b..9519b921b 100644
--- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
+++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
@@ -898,7 +898,12 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato
$stepKey,
$customActionAttributes['class'] . '::' . $customActionAttributes['method']
);
- $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $arguments);
+ $testSteps .= $this->wrapFunctionCallWithReturnValue(
+ $stepKey,
+ $actor,
+ $actionObject,
+ $arguments
+ );
break;
case "createData":
$entity = $customActionAttributes['entity'];
@@ -2016,16 +2021,7 @@ private function addDollarSign($input)
*/
private function wrapFunctionCall($actor, $action, ...$args)
{
- $isFirst = true;
- $isActionHelper = $action->getType() === 'helper';
- $actionType = $action->getType();
- if ($isActionHelper) {
- $actor = "this->helperContainer->get('" . $action->getCustomActionAttributes()['class'] . "')";
- $args = $args[0];
- $actionType = $action->getCustomActionAttributes()['method'];
- }
-
- $output = sprintf("\t\t$%s->%s(", $actor, $actionType);
+ $output = sprintf("\t\t$%s->%s(", $actor, $action->getType());
for ($i = 0; $i < count($args); $i++) {
if (null === $args[$i]) {
continue;
@@ -2046,17 +2042,22 @@ private function wrapFunctionCall($actor, $action, ...$args)
/**
* Wrap parameters into a function call with a return value.
*
- * @param string $returnVariable
- * @param string $actor
- * @param string $action
- * @param array ...$args
+ * @param string $returnVariable
+ * @param string $actor
+ * @param actionObject $action
+ * @param array ...$args
* @return string
* @throws \Exception
*/
private function wrapFunctionCallWithReturnValue($returnVariable, $actor, $action, ...$args)
{
- $isFirst = true;
- $output = sprintf("\t\t$%s = $%s->%s(", $returnVariable, $actor, $action->getType());
+ $actionType = $action->getType();
+ if ($actionType === 'helper') {
+ $actor = "this->helperContainer->get('" . $action->getCustomActionAttributes()['class'] . "')";
+ $args = $args[0];
+ $actionType = $action->getCustomActionAttributes()['method'];
+ }
+ $output = sprintf("\t\t$%s = $%s->%s(", $returnVariable, $actor, $actionType);
for ($i = 0; $i < count($args); $i++) {
if (null === $args[$i]) {
continue;