diff --git a/dev/tests/verification/TestModule/Test/AssertTest.xml b/dev/tests/verification/TestModule/Test/AssertTest.xml
index 8cdc724cc..753ccedf1 100644
--- a/dev/tests/verification/TestModule/Test/AssertTest.xml
+++ b/dev/tests/verification/TestModule/Test/AssertTest.xml
@@ -157,47 +157,157 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ apple
+ ['orange' => 2, 'apple' => 1]
+
+
+ kiwi
+ ['orange' => 2, 'apple' => 1]
+
+
+ [1, 2, 3, 5]
+ [1, 2]
+
+
+ ab
+ ['item1' => 'a', 'item2' => 'ab']
+
+
+ ['a', 'b']
+ 2
+
+
+ []
+
+
+ Copyright © 2013-2017 Magento, Inc. All rights reserved.
+ text
+
+
+ text
+ Copyright © 2013-2017 Magento, Inc. All rights reserved.
+
+
+ 0
+
+
+ /out.txt
+
+
+ $text
+
+
+ 5
+ 2
+
+
+ 5
+ 2
+
+
+ 5
+ 2
+
+
+ xyz
+ string
+
+
+ 21
+ int
+
+
+ $text
+ string
+
+
+ 2
+ 5
+
+
+ 2
+ 5
+
+
+ 2
+ 5
+
+
+ bc
+ ['item1' => 'a', 'item2' => 'ab']
+
+
+ text
+ bc
+
+
+ [1, 2]
+
+
+ text
+
+
+ 5
+ 2
+
+
+ abc
+
+
+ text
+
+
+ bar
+ /foo/
+
+
+ tag
+ log
+
+
+ foo
+ /foo/
+
+
+ bar
+ bar
+
+
+ banana
+ a
+
+
+ apple
+ a
+
+
+ 1
+
+
+ admin__control-text
+
+
+ text
+ User::class
+
+
+ 21
+ User::class
+
+
+ text
+
+
+ text
+
+
+ text
+
+
+ new MyException('exception msg')
+ function() {$this->doSomethingBad();}
+
@@ -263,29 +373,29 @@
-
- admin__control-text
+
+ admin__control-text
-
- login[username]
+
+ login[username]
-
- true
+
+ true
-
- {required:true}
+
+ {required:true}
-
- display: none;
+
+ display: none;
-
- 0
+
+ 0
-
- $createData2.firstname$
+
+ $createData2.firstname$
-
- $$createData1.firstname$$
+
+ $$createData1.firstname$$
diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php
index 4d2d45d1f..0ae3d336e 100644
--- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php
+++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php
@@ -56,10 +56,10 @@ class ActionObject
"command",
"html"
];
- const OLD_ASSERTION_ATTRIBUTES = ["expected", "expectedType", "actual", "actualType"];
const ASSERTION_ATTRIBUTES = ["expectedResult" => "expected", "actualResult" => "actual"];
const ASSERTION_TYPE_ATTRIBUTE = "type";
const ASSERTION_VALUE_ATTRIBUTE = "value";
+ const ASSERTION_ELEMENT_ATTRIBUTES = ["selector", "attribute"];
const DELETE_DATA_MUTUAL_EXCLUSIVE_ATTRIBUTES = ["url", "createDataKey"];
const EXTERNAL_URL_AREA_INVALID_ACTIONS = ['amOnPage'];
const FUNCTION_CLOSURE_ACTIONS = ['waitForElementChange'];
@@ -303,24 +303,6 @@ public function resolveReferences()
public function trimAssertionAttributes()
{
$actionAttributeKeys = array_keys($this->actionAttributes);
-
- /** MQE-683 DEPRECATE OLD METHOD HERE
- * Checks if action has any of the old, single line attributes
- * Throws a warning and returns, assuming old syntax is used.
- */
- $oldAttributes = array_intersect($actionAttributeKeys, ActionObject::OLD_ASSERTION_ATTRIBUTES);
- if (!empty($oldAttributes)) {
- $appConfig = MftfApplicationConfig::getConfig();
- if ($appConfig->getPhase() == MftfApplicationConfig::GENERATION_PHASE && $appConfig->verboseEnabled()) {
- LoggingUtil::getInstance()->getLogger(ActionObject::class)->deprecation(
- "use of one line Assertion actions will be deprecated in MFTF 3.0.0, please use nested syntax",
- ["action" => $this->type, "stepKey" => $this->stepKey],
- true
- );
- }
- return;
- }
-
$relevantKeys = array_keys(ActionObject::ASSERTION_ATTRIBUTES);
$relevantAssertionAttributes = array_intersect($actionAttributeKeys, $relevantKeys);
@@ -328,47 +310,25 @@ public function trimAssertionAttributes()
return;
}
- $this->validateAssertionSchema($relevantAssertionAttributes);
-
// Flatten nested Elements's type and value into key=>value entries
+ // Also, add selector/value attributes if they are present in nested Element
foreach ($this->actionAttributes as $key => $subAttributes) {
+ foreach (self::ASSERTION_ELEMENT_ATTRIBUTES as $ATTRIBUTE) {
+ if (isset($subAttributes[$ATTRIBUTE])) {
+ $this->actionAttributes[$ATTRIBUTE] = $subAttributes[$ATTRIBUTE];
+ }
+ }
if (in_array($key, $relevantKeys)) {
$prefix = ActionObject::ASSERTION_ATTRIBUTES[$key];
$this->actionAttributes[$prefix . ucfirst(ActionObject::ASSERTION_TYPE_ATTRIBUTE)] =
- $subAttributes[ActionObject::ASSERTION_TYPE_ATTRIBUTE];
+ $subAttributes[ActionObject::ASSERTION_TYPE_ATTRIBUTE] ?? "NO_TYPE";
$this->actionAttributes[$prefix] =
- $subAttributes[ActionObject::ASSERTION_VALUE_ATTRIBUTE];
+ $subAttributes[ActionObject::ASSERTION_VALUE_ATTRIBUTE] ?? "";
unset($this->actionAttributes[$key]);
}
}
}
- /**
- * Validates that the given assertion attributes have valid schema according to nested assertion syntax.
- * @param array $attributes
- * @return void
- * @throws TestReferenceException
- */
- private function validateAssertionSchema($attributes)
- {
- /** MQE-683 DEPRECATE OLD METHOD HERE
- * Unnecessary validation, only needed for backwards compatibility
- */
- $singleChildTypes = ['assertEmpty', 'assertFalse', 'assertFileExists', 'assertFileNotExists',
- 'assertIsEmpty', 'assertNotEmpty', 'assertNotNull', 'assertNull', 'assertTrue',
- 'assertElementContainsAttribute'];
-
- if (!in_array($this->type, $singleChildTypes)) {
- if (!in_array('expectedResult', $attributes)
- || !in_array('actualResult', $attributes)) {
- throw new TestReferenceException(
- "{$this->type} must have both an expectedResult & actualResult defined (stepKey: {$this->stepKey})",
- ["action" => $this->type, "stepKey" => $this->stepKey]
- );
- }
- }
- }
-
/**
* Look up the selector for SomeSectionName.ElementName and set it as the selector attribute in the
* resolved custom attributes. Also set the timeout value.
diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd
index 4fdde9990..22f306382 100644
--- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd
+++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd
@@ -49,22 +49,6 @@
-
-
-
- Assertion's Expected value. Cast by expectedType.
-
-
-
-
-
-
-
- Assertion's Actual value. Cast by actualType.
-
-
-
-
@@ -92,16 +76,11 @@
-
-
-
-
-
@@ -115,23 +94,8 @@
-
+
-
-
-
- Assertion's Expected value. Cast by expectedType.
-
-
-
-
-
-
-
- Attribute in given element to be assert against.
-
-
-
@@ -145,10 +109,6 @@
-
-
-
-
@@ -163,10 +123,6 @@
-
-
-
-
@@ -181,10 +137,6 @@
-
-
-
-
@@ -200,10 +152,6 @@
-
-
-
-
@@ -218,10 +166,6 @@
-
-
-
-
@@ -235,10 +179,6 @@
-
-
-
-
@@ -253,10 +193,6 @@
-
-
-
-
@@ -271,10 +207,6 @@
-
-
-
-
@@ -288,10 +220,6 @@
-
-
-
-
@@ -305,10 +233,6 @@
-
-
-
-
@@ -323,10 +247,6 @@
-
-
-
-
@@ -341,10 +261,6 @@
-
-
-
-
@@ -359,10 +275,6 @@
-
-
-
-
@@ -377,10 +289,6 @@
-
-
-
-
@@ -395,10 +303,6 @@
-
-
-
-
@@ -412,10 +316,6 @@
-
-
-
-
@@ -430,10 +330,6 @@
-
-
-
-
@@ -448,10 +344,6 @@
-
-
-
-
@@ -466,10 +358,6 @@
-
-
-
-
@@ -484,10 +372,6 @@
-
-
-
-
@@ -501,10 +385,6 @@
-
-
-
-
@@ -519,10 +399,6 @@
-
-
-
-
@@ -538,10 +414,6 @@
-
-
-
-
@@ -555,10 +427,6 @@
-
-
-
-
@@ -573,10 +441,6 @@
-
-
-
-
@@ -591,10 +455,6 @@
-
-
-
-
@@ -608,10 +468,6 @@
-
-
-
-
@@ -626,10 +482,6 @@
-
-
-
-
@@ -644,10 +496,6 @@
-
-
-
-
@@ -662,10 +510,6 @@
-
-
-
-
@@ -680,10 +524,6 @@
-
-
-
-
@@ -697,10 +537,6 @@
-
-
-
-
@@ -715,10 +551,6 @@
-
-
-
-
@@ -735,6 +567,20 @@
+
+
+
+ Element containing the Expected value and selector/attributeName.
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php
new file mode 100644
index 000000000..09eafa483
--- /dev/null
+++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php
@@ -0,0 +1,159 @@
+ actions to be nested as possible
+ * WILL NOT CATCH cases where style is a mix of old and new
+ *
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return string
+ */
+ public function execute(InputInterface $input, OutputInterface $output)
+ {
+ $testsPath = $input->getArgument('path');
+ $finder = new Finder();
+ $finder->files()->in($testsPath)->name("*.xml");
+
+ $fileSystem = new Filesystem();
+ $testsUpdated = 0;
+ foreach ($finder->files() as $file) {
+ $contents = $file->getContents();
+ // Isolate but never ... , stops after finding first />
+ preg_match_all('//', $contents, $potentialAssertions);
+ $newAssertions = [];
+ $index = 0;
+ if (empty($potentialAssertions[0])) {
+ continue;
+ }
+ foreach ($potentialAssertions[0] as $potentialAssertion) {
+ $newAssertions[$index] = $this->convertOldAssertionToNew($potentialAssertion);
+ $index++;
+ }
+ foreach ($newAssertions as $currentIndex => $replacements) {
+ $contents = str_replace($potentialAssertions[0][$currentIndex], $replacements, $contents);
+ }
+ $fileSystem->dumpFile($file->getRealPath(), $contents);
+ $testsUpdated++;
+ }
+
+ return ("Assertion Syntax updated in {$testsUpdated} file(s).\n");
+ }
+
+ /**
+ * Takes given string and attempts to convert it from single line to multi-line
+ *
+ * @param string $assertion
+ * @return string
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * @SuppressWarnings(PHPMD.NPathComplexity)
+ */
+ private function convertOldAssertionToNew($assertion)
+ {
+ // assertSomething
+ $assertType = ltrim(explode(' ', $assertion)[0], '<');
+
+ // regex to all attribute=>value pairs
+ $allAttributes = "stepKey|actual|actualType|expected|expectedType|expectedValue|";
+ $allAttributes .= "delta|message|selector|attribute|before|after|remove";
+ $grabValueRegex = '/('. $allAttributes .')=(\'[^\']*\'|"[^"]*")/';
+
+ // Makes 3 arrays in $grabbedParts:
+ // 0 contains stepKey="value"
+ // 1 contains stepKey
+ // 2 contains value
+ $sortedParts = [];
+ preg_match_all($grabValueRegex, $assertion, $grabbedParts);
+ for ($i = 0; $i < count($grabbedParts[0]); $i++) {
+ $sortedParts[$grabbedParts[1][$i]] = $grabbedParts[2][$i];
+ }
+
+ // Begin trimming values and adding back into new string
+ $trimmedParts = [];
+ $newString = "<$assertType";
+ $subElements = ["actual" => [], "expected" => []];
+ foreach ($sortedParts as $type => $value) {
+ // If attribute="'value'", elseif attribute='"value"', new nested format will break if we leave these in
+ if (strpos($value, '"') === 0) {
+ $value = rtrim(ltrim($value, '"'), '"');
+ } elseif (strpos($value, "'") === 0) {
+ $value = rtrim(ltrim($value, "'"), "'");
+ }
+ // If value is empty string (" " or ' '), trim again to become empty
+ if (str_replace(" ", "", $value) == "''") {
+ $value = "";
+ } elseif (str_replace(" ", "", $value) == '""') {
+ $value = "";
+ }
+
+ // Value is ready for storage/reapply
+ $trimmedParts[$type] = $value;
+ if (in_array($type, ["stepKey", "delta", "message", "before", "after", "remove"])) {
+ // Add back as attribute safely
+ $newString .= " $type=\"$value\"";
+ continue;
+ }
+
+ // Store in subtype for child element creation
+ if ($type == "actual") {
+ $subElements["actual"]["value"] = $value;
+ } elseif ($type == "actualType") {
+ $subElements["actual"]["type"] = $value;
+ } elseif ($type == "expected" or $type == "expectedValue") {
+ $subElements["expected"]["value"] = $value;
+ } elseif ($type == "expectedType") {
+ $subElements["expected"]["type"] = $value;
+ }
+ }
+ $newString .= ">\n";
+
+ // Assert type is very edge-cased, completely different schema
+ if ($assertType == 'assertElementContainsAttribute') {
+ // assertElementContainsAttribute type defaulted to string if not present
+ if (!isset($subElements["expected"]['type'])) {
+ $subElements["expected"]['type'] = "string";
+ }
+ $value = $subElements['expected']['value'] ?? "";
+ $type = $subElements["expected"]['type'];
+ $selector = $trimmedParts['selector'];
+ $attribute = $trimmedParts['attribute'];
+ // @codingStandardsIgnoreStart
+ $newString .= "\t\t\t$value\n";
+ // @codingStandardsIgnoreEnd
+ } else {
+ // Set type to const if it's absent, old default
+ if (isset($subElements["actual"]['value']) && !isset($subElements["actual"]['type'])) {
+ $subElements["actual"]['type'] = "const";
+ }
+ if (isset($subElements["expected"]['value']) && !isset($subElements["expected"]['type'])) {
+ $subElements["expected"]['type'] = "const";
+ }
+ foreach ($subElements as $type => $subElement) {
+ if (empty($subElement)) {
+ continue;
+ }
+ $value = $subElement['value'];
+ $typeValue = $subElement['type'];
+ $newString .= "\t\t\t<{$type}Result type=\"$typeValue\">$value{$type}Result>\n";
+ }
+ }
+ $newString .= " $assertType>";
+ return $newString;
+ }
+}
diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php
index b4858241a..6293b589b 100644
--- a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php
+++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php
@@ -29,6 +29,7 @@ public function __construct(array $scripts = [])
{
$this->scripts = [
'upgradeTestSchema' => new UpdateTestSchemaPaths(),
+ 'upgradeAssertionSchema' => new UpdateAssertionSchema(),
'renameMetadataFiles' => new RenameMetadataFiles(),
'removeModuleFileInSuiteFiles' => new RemoveModuleFileInSuiteFiles(),
'splitMultipleEntitiesFiles' => new SplitMultipleEntitiesFiles(),
diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
index ac367449f..275c01c8f 100644
--- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
+++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php
@@ -623,9 +623,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato
} elseif (isset($customActionAttributes['url'])) {
$input = $this->addUniquenessFunctionCall($customActionAttributes['url']);
$url = $this->addUniquenessFunctionCall($customActionAttributes['url']);
- } elseif (isset($customActionAttributes['expectedValue'])) {
- //For old Assert backwards Compatibility, remove when deprecating
- $assertExpected = $this->addUniquenessFunctionCall($customActionAttributes['expectedValue']);
} elseif (isset($customActionAttributes['regex'])) {
$input = $this->addUniquenessFunctionCall($customActionAttributes['regex']);
}