diff --git a/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt b/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt new file mode 100644 index 000000000..a62548ccc --- /dev/null +++ b/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt @@ -0,0 +1,38 @@ +fillField("#foo", "foo"); + $I->fillField("#bar", "bar"); + $I->click("#foo2"); + $I->click("#bar2"); + $I->click("#baz2"); + $I->fillField("#baz", "baz"); + } +} diff --git a/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt b/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt new file mode 100644 index 000000000..504ca8120 --- /dev/null +++ b/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt @@ -0,0 +1,38 @@ +fillField("#foo", "foo"); + $I->click("#foo2"); + $I->click("#bar2"); + $I->click("#baz2"); + $I->fillField("#bar", "bar"); + $I->fillField("#baz", "baz"); + } +} diff --git a/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt b/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt new file mode 100644 index 000000000..9ffc3d452 --- /dev/null +++ b/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt @@ -0,0 +1,38 @@ +fillField("#foo", "foo"); + $I->fillField("#bar", "bar"); + $I->click("#mergeOne"); + $I->click("#mergeTwo"); + $I->click("#mergeThree"); + $I->fillField("#baz", "baz"); + } +} diff --git a/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt b/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt new file mode 100644 index 000000000..a830c218c --- /dev/null +++ b/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt @@ -0,0 +1,38 @@ +fillField("#foo", "foo"); + $I->click("#mergeOne"); + $I->click("#mergeTwo"); + $I->click("#mergeThree"); + $I->fillField("#bar", "bar"); + $I->fillField("#baz", "baz"); + } +} diff --git a/dev/tests/verification/Resources/MergedActionGroupTest.txt b/dev/tests/verification/Resources/MergedActionGroupTest.txt index 59f2b2643..f6c8f2351 100644 --- a/dev/tests/verification/Resources/MergedActionGroupTest.txt +++ b/dev/tests/verification/Resources/MergedActionGroupTest.txt @@ -70,9 +70,9 @@ class MergedActionGroupTestCest */ public function MergedActionGroupTest(AcceptanceTester $I) { - $I->see("#element .Jane"); $I->see(".merge .Jane"); - $I->click(".merge .Dane"); + $I->see("#element .Jane"); $I->amOnPage("/Jane/Dane.html"); + $I->click(".merge .Dane"); } } diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml index 342299804..5e1a20f96 100644 --- a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml @@ -50,6 +50,16 @@ + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup.xml index bd478e645..7d8585772 100644 --- a/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup.xml +++ b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup.xml @@ -13,4 +13,16 @@ + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest.xml index 6a0558628..63f800983 100644 --- a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest.xml +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest.xml @@ -182,6 +182,12 @@ + + + + + + diff --git a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml b/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml index bd7c23522..92b04e0ad 100644 --- a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml +++ b/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml @@ -119,4 +119,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/dev/tests/verification/TestModule/Test/MergeFunctionalTest.xml b/dev/tests/verification/TestModule/Test/MergeFunctionalTest.xml index 75c62b36f..553f3d251 100644 --- a/dev/tests/verification/TestModule/Test/MergeFunctionalTest.xml +++ b/dev/tests/verification/TestModule/Test/MergeFunctionalTest.xml @@ -45,4 +45,14 @@ + + + + + + + + + + diff --git a/dev/tests/verification/Tests/ActionGroupMergeGenerationTest.php b/dev/tests/verification/Tests/ActionGroupMergeGenerationTest.php index 9176f3955..0361bec75 100644 --- a/dev/tests/verification/Tests/ActionGroupMergeGenerationTest.php +++ b/dev/tests/verification/Tests/ActionGroupMergeGenerationTest.php @@ -108,4 +108,26 @@ public function testArgumentWithSameNameAsElement() { $this->generateAndCompareTest('ArgumentWithSameNameAsElement'); } + + /** + * Test an action group with a merge counterpart that's merged via insertBefore + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testMergedActionGroupViaInsertBefore() + { + $this->generateAndCompareTest('ActionGroupMergedViaInsertBefore'); + } + + /** + * Test an action group with a merge counterpart that's merged via insertAfter + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testMergedActionGroupViaInsertAfter() + { + $this->generateAndCompareTest('ActionGroupMergedViaInsertAfter'); + } } diff --git a/dev/tests/verification/Tests/MergedGenerationTest.php b/dev/tests/verification/Tests/MergedGenerationTest.php index fe2990b76..9ef22fe09 100644 --- a/dev/tests/verification/Tests/MergedGenerationTest.php +++ b/dev/tests/verification/Tests/MergedGenerationTest.php @@ -40,4 +40,26 @@ public function testParsedArray() $entity = DataObjectHandler::getInstance()->getObject('testEntity'); $this->assertCount(3, $entity->getLinkedEntities()); } + + /** + * Tests generation of a test merge file via insertBefore + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testMergeMassViaInsertBefore() + { + $this->generateAndCompareTest('MergeMassViaInsertBefore'); + } + + /** + * Tests generation of a test merge file via insertBefore + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testMergeMassViaInsertAfter() + { + $this->generateAndCompareTest('MergeMassViaInsertAfter'); + } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Config/ActionGroupDom.php b/src/Magento/FunctionalTestingFramework/Test/Config/ActionGroupDom.php index 794007dde..bfe1c243f 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Config/ActionGroupDom.php +++ b/src/Magento/FunctionalTestingFramework/Test/Config/ActionGroupDom.php @@ -30,9 +30,25 @@ public function initDom($xml, $filename = null, $exceptionCollector = null) /** @var \DOMElement $actionGroupNode */ $actionGroupNode->setAttribute(self::TEST_META_FILENAME_ATTRIBUTE, $filename); $this->validateDomStepKeys($actionGroupNode, $filename, 'Action Group', $exceptionCollector); + if ($actionGroupNode->getAttribute(self::TEST_MERGE_POINTER_AFTER) !== "") { + $this->appendMergePointerToActions( + $actionGroupNode, + self::TEST_MERGE_POINTER_AFTER, + $actionGroupNode->getAttribute(self::TEST_MERGE_POINTER_AFTER), + $filename, + $exceptionCollector + ); + } elseif ($actionGroupNode->getAttribute(self::TEST_MERGE_POINTER_BEFORE) !== "") { + $this->appendMergePointerToActions( + $actionGroupNode, + self::TEST_MERGE_POINTER_BEFORE, + $actionGroupNode->getAttribute(self::TEST_MERGE_POINTER_BEFORE), + $filename, + $exceptionCollector + ); + } } } - return $dom; } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Config/Dom.php b/src/Magento/FunctionalTestingFramework/Test/Config/Dom.php index 24710243f..fb7b0a386 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Config/Dom.php +++ b/src/Magento/FunctionalTestingFramework/Test/Config/Dom.php @@ -10,6 +10,7 @@ use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\Config\Dom\NodeMergingConfig; use Magento\FunctionalTestingFramework\Config\Dom\NodePathMatcher; +use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; class Dom extends \Magento\FunctionalTestingFramework\Config\Dom { @@ -17,6 +18,8 @@ class Dom extends \Magento\FunctionalTestingFramework\Config\Dom const TEST_META_FILENAME_ATTRIBUTE = 'filename'; const TEST_META_NAME_ATTRIBUTE = 'name'; const TEST_HOOK_NAMES = ["after", "before"]; + const TEST_MERGE_POINTER_BEFORE = "insertBefore"; + const TEST_MERGE_POINTER_AFTER = "insertAfter"; /** * TestDom constructor. @@ -63,6 +66,23 @@ public function initDom($xml, $filename = null, $exceptionCollector = null) /** @var \DOMElement $testNode */ $testNode->setAttribute(self::TEST_META_FILENAME_ATTRIBUTE, $filename); $this->validateDomStepKeys($testNode, $filename, 'Test', $exceptionCollector); + if ($testNode->getAttribute(self::TEST_MERGE_POINTER_AFTER) !== "") { + $this->appendMergePointerToActions( + $testNode, + self::TEST_MERGE_POINTER_AFTER, + $testNode->getAttribute(self::TEST_MERGE_POINTER_AFTER), + $filename, + $exceptionCollector + ); + } elseif ($testNode->getAttribute(self::TEST_MERGE_POINTER_BEFORE) !== "") { + $this->appendMergePointerToActions( + $testNode, + self::TEST_MERGE_POINTER_BEFORE, + $testNode->getAttribute(self::TEST_MERGE_POINTER_BEFORE), + $filename, + $exceptionCollector + ); + } } } @@ -83,6 +103,41 @@ public function merge($xml, $filename = null, $exceptionCollector = null) $this->mergeNode($dom->documentElement, ''); } + /** + * Parses DOM Structure's actions and appends a before/after attribute along with the parent's stepkey reference. + * + * @param \DOMElement $testNode + * @param string $insertType + * @param string $insertKey + * @param string $filename + * @param ExceptionCollector $exceptionCollector + * @return void + */ + protected function appendMergePointerToActions($testNode, $insertType, $insertKey, $filename, $exceptionCollector) + { + $childNodes = $testNode->childNodes; + $previousStepKey = $insertKey; + $actionInsertType = ActionObject::MERGE_ACTION_ORDER_AFTER; + if ($insertType == self::TEST_MERGE_POINTER_BEFORE) { + $actionInsertType = ActionObject::MERGE_ACTION_ORDER_BEFORE; + } + for ($i = 0; $i < $childNodes->length; $i++) { + $currentNode = $childNodes->item($i); + if (!is_a($currentNode, \DOMElement::class) || !$currentNode->hasAttribute('stepKey')) { + continue; + } + if ($currentNode->hasAttribute($insertType) && $testNode->hasAttribute($insertType)) { + $errorMsg = "Actions cannot have merge pointers if contained in tests that has a merge pointer."; + $errorMsg .= "\n\tstepKey: {$currentNode->getAttribute('stepKey')}\tin file: {$filename}"; + $exceptionCollector->addError($filename, $errorMsg); + } + $currentNode->setAttribute($actionInsertType, $previousStepKey); + $previousStepKey = $currentNode->getAttribute('stepKey'); + // All actions after the first need to insert AFTER. + $actionInsertType = ActionObject::MERGE_ACTION_ORDER_AFTER; + } + } + /** * Parses an individual DOM structure for repeated stepKey attributes * diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php index 5c8b5bfb2..7cd73f120 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php @@ -137,6 +137,12 @@ private function getResolvedActionsWithArgs($arguments, $actionReferenceKey) ); } + // translate 0/1 back to before/after + $orderOffset = ActionObject::MERGE_ACTION_ORDER_BEFORE; + if ($action->getOrderOffset() === 1) { + $orderOffset = ActionObject::MERGE_ACTION_ORDER_AFTER; + } + // 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() . ucfirst($actionReferenceKey)] = new ActionObject( @@ -144,7 +150,7 @@ private function getResolvedActionsWithArgs($arguments, $actionReferenceKey) $action->getType(), array_replace_recursive($action->getCustomActionAttributes(), $newActionAttributes), $action->getLinkedAction() == null ? null : $action->getLinkedAction() . ucfirst($actionReferenceKey), - $action->getOrderOffset(), + $orderOffset, [self::ACTION_GROUP_ORIGIN_NAME => $this->name, self::ACTION_GROUP_ORIGIN_TEST_REF => $actionReferenceKey] ); diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php index 32b54c3da..9fd912da3 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php @@ -19,6 +19,8 @@ class ActionGroupObjectExtractor extends BaseObjectExtractor const DEFAULT_VALUE = 'defaultValue'; const ACTION_GROUP_ARGUMENTS = 'arguments'; const FILENAME = 'filename'; + const ACTION_GROUP_INSERT_BEFORE = "insertBefore"; + const ACTION_GROUP_INSERT_AFTER = "insertAfter"; /** * Action Object Extractor for converting actions into objects @@ -51,7 +53,9 @@ public function extractActionGroup($actionGroupData) self::NODE_NAME, self::ACTION_GROUP_ARGUMENTS, self::NAME, - self::FILENAME + self::FILENAME, + self::ACTION_GROUP_INSERT_BEFORE, + self::ACTION_GROUP_INSERT_AFTER ); // TODO filename is now available to the ActionGroupObject, integrate this into debug and error statements diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php index 4bc120f2e..b4188abe0 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php @@ -18,7 +18,7 @@ class ActionMergeUtil { const STEP_MISSING_ERROR_MSG = "Merge Error - Step could not be found in either TestXML or DeltaXML. - \t%s = '%s'\tTestStep='%s'\tLinkedStep'%s'"; + \t%s: '%s'\tTestStep: '%s'\tLinkedStep: '%s'"; const WAIT_ATTR = 'timeout'; const WAIT_ACTION_NAME = 'waitForPageLoad'; diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php index 9dc4b0652..cd39753ba 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php @@ -21,6 +21,11 @@ class TestObjectExtractor extends BaseObjectExtractor const TEST_BEFORE_HOOK = 'before'; const TEST_AFTER_HOOK = 'after'; const TEST_FAILED_HOOK = 'failed'; + const TEST_BEFORE_ATTRIBUTE = 'before'; + const TEST_AFTER_ATTRIBUTE = 'after'; + const TEST_INSERT_BEFORE = 'insertBefore'; + const TEST_INSERT_AFTER = 'insertAfter'; + const TEST_FILENAME = 'filename'; /** * Action Object Extractor object @@ -80,7 +85,9 @@ public function extractTestData($testData) self::TEST_BEFORE_HOOK, self::TEST_AFTER_HOOK, self::TEST_FAILED_HOOK, - 'filename' + self::TEST_INSERT_BEFORE, + self::TEST_INSERT_AFTER, + self::TEST_FILENAME ); if (array_key_exists(self::TEST_ANNOTATIONS, $testData)) { @@ -91,7 +98,7 @@ public function extractTestData($testData) $testAnnotations["features"] = [$module]; // extract before - if (array_key_exists(self::TEST_BEFORE_HOOK, $testData)) { + if (array_key_exists(self::TEST_BEFORE_HOOK, $testData) && is_array($testData[self::TEST_BEFORE_HOOK])) { $testHooks[self::TEST_BEFORE_HOOK] = $this->testHookObjectExtractor->extractHook( $testData[self::NAME], 'before', @@ -99,7 +106,7 @@ public function extractTestData($testData) ); } - if (array_key_exists(self::TEST_AFTER_HOOK, $testData)) { + if (array_key_exists(self::TEST_AFTER_HOOK, $testData) && is_array($testData[self::TEST_AFTER_HOOK])) { // extract after $testHooks[self::TEST_AFTER_HOOK] = $this->testHookObjectExtractor->extractHook( $testData[self::NAME], diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd index 74badd40c..5df793643 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd @@ -33,6 +33,8 @@ + + diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd index 012083ab8..ecd058581 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd @@ -70,6 +70,8 @@ + +