diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt
index cebccc5d1..57bd9dd01 100644
--- a/dev/tests/verification/Resources/BasicFunctionalTest.txt
+++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt
@@ -94,6 +94,7 @@ class BasicFunctionalTestCest
$I->dontSeeOptionIsSelected(".functionalTestSelector", "someInput");
$I->doubleClick(".functionalTestSelector");
$I->dragAndDrop(".functionalTestSelector", ".functionalTestSelector2");
+ $I->dragAndDrop(".functionalTestSelector", ".functionalTestSelector2", 100, 900);
$executeJSKey1 = $I->executeJS("someJSFunction");
$I->fillField(".functionalTestSelector", "someInput");
$I->fillField(".functionalTestSelector", "0");
diff --git a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml b/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml
index 9af9187a8..bd7c23522 100644
--- a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml
+++ b/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml
@@ -56,6 +56,7 @@
+
diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php
index 3736433f5..1917e8bab 100644
--- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php
+++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php
@@ -13,6 +13,7 @@
use Facebook\WebDriver\WebDriverSelect;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\Exception\NoSuchElementException;
+use Facebook\WebDriver\Interactions\WebDriverActions;
use Codeception\Exception\ElementNotFound;
use Codeception\Exception\ModuleConfigException;
use Codeception\Exception\ModuleException;
@@ -526,6 +527,36 @@ public function _before(TestInterface $test)
parent::_before($test);
}
+ /**
+ * Override for codeception's default dragAndDrop to include offset options.
+ * @param string $source
+ * @param string $target
+ * @param int $xOffset
+ * @param int $yOffset
+ * @return void
+ */
+ public function dragAndDrop($source, $target, $xOffset = null, $yOffset = null)
+ {
+ if ($xOffset !== null || $yOffset !== null) {
+ $snodes = $this->matchFirstOrFail($this->baseElement, $source);
+ $tnodes = $this->matchFirstOrFail($this->baseElement, $target);
+
+ $targetX = intval($tnodes->getLocation()->getX() + $xOffset);
+ $targetY = intval($tnodes->getLocation()->getY() + $yOffset);
+
+ $travelX = intval($targetX - $snodes->getLocation()->getX());
+ $travelY = intval($targetY - $snodes->getLocation()->getY());
+
+ $action = new WebDriverActions($this->webDriver);
+ $action->moveToElement($snodes)->perform();
+ $action->clickAndHold($snodes)->perform();
+ $action->moveByOffset($travelX, $travelY)->perform();
+ $action->release()->perform();
+ } else {
+ parent::dragAndDrop($source, $target);
+ }
+ }
+
/**
* Override for _failed method in Codeception method. Adds png and html attachments to allure report
* following parent execution of test failure processing.
diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/actionTypeTags.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/actionTypeTags.xsd
index ebb2e3570..9aa772858 100644
--- a/src/Magento/FunctionalTestingFramework/Test/etc/actionTypeTags.xsd
+++ b/src/Magento/FunctionalTestingFramework/Test/etc/actionTypeTags.xsd
@@ -269,7 +269,22 @@
End point selector for drag-and-drop.
-
+
+
+
+
+
+ X offset for drag-and-drop destination.
+
+
+
+
+
+
+ Y offset for drag-and-drop destination.
+
+
+
diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
index ac1402c47..211f010c0 100644
--- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
+++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
@@ -980,7 +980,7 @@ public function generateStepsPhp($actionObjects, $hookObject = false, $actor = "
$testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $parameterArray, $button);
break;
case "dragAndDrop":
- $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector1, $selector2);
+ $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector1, $selector2, $x, $y);
break;
case "selectMultipleOptions":
$testSteps .= $this->wrapFunctionCall(