From 61027d915f18b1ae235cf21a5214f038758a8760 Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Thu, 27 Feb 2020 08:59:46 -0600 Subject: [PATCH 01/12] MQE-683: [Deprecation] Only use more nested assertion syntax - Deprecated one-line syntax - added upgrade script --- .../Test/Objects/ActionObject.php | 47 ------ .../Test/etc/Actions/assertActions.xsd | 136 ------------------ .../Upgrade/UpdateAssertionSchema.php | 126 ++++++++++++++++ .../Upgrade/UpgradeScriptList.php | 1 + 4 files changed, 127 insertions(+), 183 deletions(-) create mode 100644 src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index f377e2fac..a3bbd3cf3 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -56,7 +56,6 @@ 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"; @@ -303,24 +302,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,8 +309,6 @@ public function trimAssertionAttributes() return; } - $this->validateAssertionSchema($relevantAssertionAttributes); - // Flatten nested Elements's type and value into key=>value entries foreach ($this->actionAttributes as $key => $subAttributes) { if (in_array($key, $relevantKeys)) { @@ -343,32 +322,6 @@ public function trimAssertionAttributes() } } - /** - * 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..b06e156e6 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd @@ -98,10 +98,6 @@ - - - - @@ -145,10 +141,6 @@ - - - - @@ -163,10 +155,6 @@ - - - - @@ -181,10 +169,6 @@ - - - - @@ -200,10 +184,6 @@ - - - - @@ -218,10 +198,6 @@ - - - - @@ -235,10 +211,6 @@ - - - - @@ -253,10 +225,6 @@ - - - - @@ -271,10 +239,6 @@ - - - - @@ -288,10 +252,6 @@ - - - - @@ -305,10 +265,6 @@ - - - - @@ -323,10 +279,6 @@ - - - - @@ -341,10 +293,6 @@ - - - - @@ -359,10 +307,6 @@ - - - - @@ -377,10 +321,6 @@ - - - - @@ -395,10 +335,6 @@ - - - - @@ -412,10 +348,6 @@ - - - - @@ -430,10 +362,6 @@ - - - - @@ -448,10 +376,6 @@ - - - - @@ -466,10 +390,6 @@ - - - - @@ -484,10 +404,6 @@ - - - - @@ -501,10 +417,6 @@ - - - - @@ -519,10 +431,6 @@ - - - - @@ -538,10 +446,6 @@ - - - - @@ -555,10 +459,6 @@ - - - - @@ -573,10 +473,6 @@ - - - - @@ -591,10 +487,6 @@ - - - - @@ -608,10 +500,6 @@ - - - - @@ -626,10 +514,6 @@ - - - - @@ -644,10 +528,6 @@ - - - - @@ -662,10 +542,6 @@ - - - - @@ -680,10 +556,6 @@ - - - - @@ -697,10 +569,6 @@ - - - - @@ -715,10 +583,6 @@ - - - - diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php new file mode 100644 index 000000000..6eca6a11e --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -0,0 +1,126 @@ + actions to be nested + * + * @param InputInterface $input + * @return string + */ + public function execute(InputInterface $input) + { + $testsPath = $input->getArgument('path'); + $finder = new Finder(); + $finder->files()->in($testsPath)->name("*.xml"); + + $fileSystem = new Filesystem(); + $testsUpdated = 0; + foreach ($finder->files() as $file) { + if (!$this->detectOldAttributes($file)) { + continue; + } + $this->currentFile = $file->getFilename(); + $contents = $file->getContents(); + // Isolate but not + preg_match_all('/]*\/>/', $contents, $potentialAssertions); + $newAssertions = []; + $index = 0; + 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" . implode("\n\t", $this->errors)); + } + + private function detectOldAttributes($file) + { + foreach (self::OLD_ASSERTION_ATTRIBUTES as $OLD_ASSERTION_ATTRIBUTE) { + if (strpos($file->getContents(), $OLD_ASSERTION_ATTRIBUTE) !== false) { + return true; + } + } + return false; + } + + private function convertOldAssertionToNew($assertion) + { + // assertSomething + $assertType = ltrim(explode(' ', $assertion)[0], '<'); + $stepKey = ""; + + // regex to grab values + $grabValueRegex = '/(stepKey|actual|actualType|expected|expectedType|delta|message)="([^"]*)"/'; + + // Make 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]; + } + + // Build new String + $newString = "<$assertType "; + $subElements = ["actual" => [], "expected" => []]; + foreach ($sortedParts as $type => $value) { + if (in_array($type, ["stepKey", "delta", "message"])) { + if ($type == "stepKey") { + $stepKey = $value; + } + $newString .= "$type=\"$value\""; + continue; + } + if ($type == "actual") { + $subElements["actual"]["value"] = $value; + } elseif ($type == "actualType") { + $subElements["actual"]["type"] = $value; + } elseif ($type == "expected") { + $subElements["expected"]["value"] = $value; + } elseif ($type == "expectedType") { + $subElements["expected"]["type"] = $value; + } + } + $newString .= ">\n"; + foreach ($subElements as $type => $subElement) { + if (!isset($subElement['value']) || !isset($subElement['type'])) { + //don't have all the info we need to rebuild + $this->errors[] = "UNABLE TO FULLY REBUILD ASSERTION, PLEASE MANUALLY CHECK FORMAT ($assertType \"$stepKey\" in $this->currentFile)"; + continue; + } + $value = $subElement['value']; + $typeValue = $subElement['type']; + $newString .= "<{$type}Result type=\"$typeValue\">$value\n"; + } + $newString .= ""; + return $newString; + } + +} diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php index 245f95d82..949b2bb0a 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(), ] + $scripts; } From 35818bb40393f552ae303746a39f7fda4cc5a246 Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Thu, 27 Feb 2020 16:05:15 -0600 Subject: [PATCH 02/12] MQE-683: [Deprecation] Only use more nested assertion syntax - static check fixes --- .../Upgrade/UpdateAssertionSchema.php | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index 6eca6a11e..c44038368 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -18,8 +18,18 @@ class UpdateAssertionSchema implements UpgradeInterface { const OLD_ASSERTION_ATTRIBUTES = ["expected", "expectedType", "actual", "actualType"]; + /** + * Current file being inspected, for error messaging + * @var string + */ private $currentFile; + + /** + * Potential errors reported during replacement. + * @var array + */ private $errors = []; + /** * Upgrades all test xml files, changing actions to be nested * @@ -40,7 +50,7 @@ public function execute(InputInterface $input) } $this->currentFile = $file->getFilename(); $contents = $file->getContents(); - // Isolate but not + // Isolate but not ... preg_match_all('/]*\/>/', $contents, $potentialAssertions); $newAssertions = []; $index = 0; @@ -58,6 +68,12 @@ public function execute(InputInterface $input) return ("Assertion Syntax updated in {$testsUpdated} file(s).\n" . implode("\n\t", $this->errors)); } + /** + * Detects present of attributes in file + * + * @param string $file + * @return boolean + */ private function detectOldAttributes($file) { foreach (self::OLD_ASSERTION_ATTRIBUTES as $OLD_ASSERTION_ATTRIBUTE) { @@ -68,6 +84,13 @@ private function detectOldAttributes($file) return false; } + /** + * Takes given string and attempts to convert it from single line to multi-line + * + * @param string $assertion + * @return string + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ private function convertOldAssertionToNew($assertion) { // assertSomething @@ -112,7 +135,8 @@ private function convertOldAssertionToNew($assertion) foreach ($subElements as $type => $subElement) { if (!isset($subElement['value']) || !isset($subElement['type'])) { //don't have all the info we need to rebuild - $this->errors[] = "UNABLE TO FULLY REBUILD ASSERTION, PLEASE MANUALLY CHECK FORMAT ($assertType \"$stepKey\" in $this->currentFile)"; + $this->errors[] = "UNABLE TO FULLY REBUILD ASSERTION, PLEASE MANUALLY CHECK FORMAT " . + "($assertType \"$stepKey\" in $this->currentFile)"; continue; } $value = $subElement['value']; @@ -122,5 +146,4 @@ private function convertOldAssertionToNew($assertion) $newString .= ""; return $newString; } - } From 173f9b36f8f0fbd518dca9c2559b4f29d2d5b328 Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Mon, 2 Mar 2020 10:53:50 -0600 Subject: [PATCH 03/12] MQE-683: [Deprecation] Only use more nested assertion syntax - Heavy updates to script - Update to AssertElementContainsAttribute action --- .../Test/Objects/ActionObject.php | 9 ++- .../Test/etc/Actions/assertActions.xsd | 24 ++++--- .../Upgrade/UpdateAssertionSchema.php | 65 ++++++++++++++----- .../Util/TestGenerator.php | 5 +- 4 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index a3bbd3cf3..6006ef879 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -59,6 +59,7 @@ class ActionObject 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']; @@ -310,11 +311,17 @@ public function trimAssertionAttributes() } // 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]; unset($this->actionAttributes[$key]); diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd index b06e156e6..ca8ebcd26 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd @@ -92,7 +92,6 @@ - @@ -111,7 +110,7 @@ - + @@ -120,14 +119,6 @@ - - - - - Attribute in given element to be assert against. - - - @@ -599,6 +590,19 @@ + + + + Element containing the Expected value and selector/attributeName. + + + + + + + + + diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index c44038368..fc1ac6011 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -54,6 +54,9 @@ public function execute(InputInterface $input) preg_match_all('/]*\/>/', $contents, $potentialAssertions); $newAssertions = []; $index = 0; + if (empty($potentialAssertions[0])) { + continue; + } foreach ($potentialAssertions[0] as $potentialAssertion) { $newAssertions[$index] = $this->convertOldAssertionToNew($potentialAssertion); $index++; @@ -98,8 +101,7 @@ private function convertOldAssertionToNew($assertion) $stepKey = ""; // regex to grab values - $grabValueRegex = '/(stepKey|actual|actualType|expected|expectedType|delta|message)="([^"]*)"/'; - + $grabValueRegex = '/(stepKey|actual|actualType|expected|expectedType|delta|message|selector|attribute|expectedValue|before|after|remove)=(\'[^\']*\'|"[^"]*")/'; // Make 3 arrays in $grabbedParts: // 0 contains stepKey="value" // 1 contains stepKey @@ -110,40 +112,69 @@ private function convertOldAssertionToNew($assertion) $sortedParts[$grabbedParts[1][$i]] = $grabbedParts[2][$i]; } - // Build new String - $newString = "<$assertType "; + // Build new String, trim ' and " + $trimmedParts = []; + $newString = "<$assertType"; $subElements = ["actual" => [], "expected" => []]; foreach ($sortedParts as $type => $value) { - if (in_array($type, ["stepKey", "delta", "message"])) { + $value = rtrim(ltrim($value, '"'), '"'); + $value = rtrim(ltrim($value, "'"), "'"); + $trimmedParts[$type] = $value; + if (in_array($type, ["stepKey", "delta", "message", "before", "after", "remove"])) { if ($type == "stepKey") { $stepKey = $value; } - $newString .= "$type=\"$value\""; + $newString .= " $type=\"$value\""; continue; } if ($type == "actual") { $subElements["actual"]["value"] = $value; } elseif ($type == "actualType") { $subElements["actual"]["type"] = $value; - } elseif ($type == "expected") { + } elseif ($type == "expected" || $type = "expectedValue") { $subElements["expected"]["value"] = $value; } elseif ($type == "expectedType") { $subElements["expected"]["type"] = $value; } } $newString .= ">\n"; - foreach ($subElements as $type => $subElement) { - if (!isset($subElement['value']) || !isset($subElement['type'])) { - //don't have all the info we need to rebuild - $this->errors[] = "UNABLE TO FULLY REBUILD ASSERTION, PLEASE MANUALLY CHECK FORMAT " . - "($assertType \"$stepKey\" in $this->currentFile)"; - continue; + // Guess value type if not set in either case + if (!isset($subElements["actual"]['type']) && isset($subElements["actual"]["value"])) { + $subElements["actual"]['type'] = $this->guessValueType($subElements["actual"]["value"]); + } + if (!isset($subElements["expected"]['type']) && isset($subElements["expected"]["value"])) { + $subElements["expected"]['type'] = $this->guessValueType($subElements["expected"]["value"]); + } + // Massage subElements with data for edge cases + if ($assertType == 'assertElementContainsAttribute') { + // Assert type is very edge-cased, completely different schema + $value = $subElements['expected']['value']; + $selector = $trimmedParts['selector']; + $attribute = $trimmedParts['attribute']; + $newString .= "\t\t\t$value\n"; + } else { + foreach ($subElements as $type => $subElement) { + if (empty($subElement)) { + continue; + } + $value = $subElement['value']; + $typeValue = $subElement['type']; + if (empty($value)) { + $this->errors[] = "POTENTIAL ANOMALOUS OUPUT DETECTED, PLEASE MANUALLY CHECK OUTPUT " . + "($assertType \"$stepKey\" in $this->currentFile)"; + } + $newString .= "\t\t\t<{$type}Result type=\"$typeValue\">$value\n"; } - $value = $subElement['value']; - $typeValue = $subElement['type']; - $newString .= "<{$type}Result type=\"$typeValue\">$value\n"; } - $newString .= ""; + $newString .= " "; return $newString; } + + private function guessValueType($string) { + preg_match('/\$[a-zA-Z0-9]*/', $string, $matches); + if (isset($matches[0]) && $matches[0] == $string) { + return "variable"; + } + return "string"; + } } diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index ab47bce7e..98645b0d1 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -617,9 +617,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']); } @@ -1234,7 +1231,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $actionObject, $selector, $this->wrapWithDoubleQuotes($attribute), - $assertExpected + $this->wrapWithDoubleQuotes($assertExpected) ); break; case "assertEmpty": From fecb9f60eba47230b6a6780ac3a09cbf26e3d01c Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Mon, 2 Mar 2020 10:59:46 -0600 Subject: [PATCH 04/12] MQE-683: [Deprecation] Only use more nested assertion syntax - Bugfix for empty value --- .../FunctionalTestingFramework/Test/Objects/ActionObject.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index 6006ef879..e71a9894d 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -323,7 +323,7 @@ public function trimAssertionAttributes() $this->actionAttributes[$prefix . ucfirst(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]); } } From e5666c152c43114ec75ae57dd1567392daed5b63 Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Mon, 2 Mar 2020 13:42:46 -0600 Subject: [PATCH 05/12] MQE-683: [Deprecation] Only use more nested assertion syntax - Update to conversion script --- .../Upgrade/UpdateAssertionSchema.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index fc1ac6011..640680469 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -117,8 +117,17 @@ private function convertOldAssertionToNew($assertion) $newString = "<$assertType"; $subElements = ["actual" => [], "expected" => []]; foreach ($sortedParts as $type => $value) { - $value = rtrim(ltrim($value, '"'), '"'); - $value = rtrim(ltrim($value, "'"), "'"); + if (strpos($value, '"') === 0) { + $value = rtrim(ltrim($value, '"'), '"'); + } elseif(strpos($value, "'") === 0) { + $value = rtrim(ltrim($value, "'"), "'"); + } + // If value is empty string, trim again + if (str_replace(" ", "", $value) == "''") { + $value = ""; + } elseif (str_replace(" ", "", $value) == '""') { + $value = ""; + } $trimmedParts[$type] = $value; if (in_array($type, ["stepKey", "delta", "message", "before", "after", "remove"])) { if ($type == "stepKey") { @@ -131,7 +140,7 @@ private function convertOldAssertionToNew($assertion) $subElements["actual"]["value"] = $value; } elseif ($type == "actualType") { $subElements["actual"]["type"] = $value; - } elseif ($type == "expected" || $type = "expectedValue") { + } elseif ($type == "expected" or $type == "expectedValue") { $subElements["expected"]["value"] = $value; } elseif ($type == "expectedType") { $subElements["expected"]["type"] = $value; @@ -159,10 +168,6 @@ private function convertOldAssertionToNew($assertion) } $value = $subElement['value']; $typeValue = $subElement['type']; - if (empty($value)) { - $this->errors[] = "POTENTIAL ANOMALOUS OUPUT DETECTED, PLEASE MANUALLY CHECK OUTPUT " . - "($assertType \"$stepKey\" in $this->currentFile)"; - } $newString .= "\t\t\t<{$type}Result type=\"$typeValue\">$value\n"; } } From ac8d76ecc98b764667dc974fe2041f1d4811180a Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Mon, 2 Mar 2020 15:11:18 -0600 Subject: [PATCH 06/12] MQE-683: [Deprecation] Only use more nested assertion syntax - More fixes --- .../Upgrade/UpdateAssertionSchema.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index 640680469..5a67bc996 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -45,9 +45,9 @@ public function execute(InputInterface $input) $fileSystem = new Filesystem(); $testsUpdated = 0; foreach ($finder->files() as $file) { - if (!$this->detectOldAttributes($file)) { - continue; - } +// if (!$this->detectOldAttributes($file)) { +// continue; +// } $this->currentFile = $file->getFilename(); $contents = $file->getContents(); // Isolate but not ... @@ -157,7 +157,7 @@ private function convertOldAssertionToNew($assertion) // Massage subElements with data for edge cases if ($assertType == 'assertElementContainsAttribute') { // Assert type is very edge-cased, completely different schema - $value = $subElements['expected']['value']; + $value = $subElements['expected']['value'] ?? ""; $selector = $trimmedParts['selector']; $attribute = $trimmedParts['attribute']; $newString .= "\t\t\t$value\n"; From 3a901e3107a2af5bf2324d312f53466b3246aa72 Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Tue, 3 Mar 2020 09:01:28 -0600 Subject: [PATCH 07/12] MQE-683: [Deprecation] Only use more nested assertion syntax - Even more fixes --- .../Upgrade/UpdateAssertionSchema.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index 5a67bc996..05bec1d31 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -147,12 +147,12 @@ private function convertOldAssertionToNew($assertion) } } $newString .= ">\n"; - // Guess value type if not set in either case - if (!isset($subElements["actual"]['type']) && isset($subElements["actual"]["value"])) { - $subElements["actual"]['type'] = $this->guessValueType($subElements["actual"]["value"]); + // Set type to const if it's absent + if (isset($subElements["actual"]['value']) && !isset($subElements["actual"]['type'])) { + $subElements["actual"]['type'] = "const"; } - if (!isset($subElements["expected"]['type']) && isset($subElements["expected"]["value"])) { - $subElements["expected"]['type'] = $this->guessValueType($subElements["expected"]["value"]); + if (isset($subElements["expected"]['value']) && !isset($subElements["expected"]['type'])) { + $subElements["expected"]['type'] = "const"; } // Massage subElements with data for edge cases if ($assertType == 'assertElementContainsAttribute') { From af17d022ffe7c0420ba4695d7ea423ec26165174 Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Tue, 3 Mar 2020 15:03:30 -0600 Subject: [PATCH 08/12] MQE-683: [Deprecation] Only use more nested assertion syntax - Cleanup --- .../Upgrade/UpdateAssertionSchema.php | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index 05bec1d31..9c8810eee 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -31,7 +31,8 @@ class UpdateAssertionSchema implements UpgradeInterface private $errors = []; /** - * Upgrades all test xml files, changing actions to be nested + * Upgrades all test xml files, changing as many actions to be nested as possible + * WILL NOT CATCH cases where style is a mix of old and new * * @param InputInterface $input * @return string @@ -45,12 +46,9 @@ public function execute(InputInterface $input) $fileSystem = new Filesystem(); $testsUpdated = 0; foreach ($finder->files() as $file) { -// if (!$this->detectOldAttributes($file)) { -// continue; -// } $this->currentFile = $file->getFilename(); $contents = $file->getContents(); - // Isolate but not ... + // Isolate but never ... preg_match_all('/]*\/>/', $contents, $potentialAssertions); $newAssertions = []; $index = 0; @@ -98,7 +96,6 @@ private function convertOldAssertionToNew($assertion) { // assertSomething $assertType = ltrim(explode(' ', $assertion)[0], '<'); - $stepKey = ""; // regex to grab values $grabValueRegex = '/(stepKey|actual|actualType|expected|expectedType|delta|message|selector|attribute|expectedValue|before|after|remove)=(\'[^\']*\'|"[^"]*")/'; @@ -130,9 +127,6 @@ private function convertOldAssertionToNew($assertion) } $trimmedParts[$type] = $value; if (in_array($type, ["stepKey", "delta", "message", "before", "after", "remove"])) { - if ($type == "stepKey") { - $stepKey = $value; - } $newString .= " $type=\"$value\""; continue; } @@ -154,7 +148,7 @@ private function convertOldAssertionToNew($assertion) if (isset($subElements["expected"]['value']) && !isset($subElements["expected"]['type'])) { $subElements["expected"]['type'] = "const"; } - // Massage subElements with data for edge cases + // Massage subElements with data for edge case if ($assertType == 'assertElementContainsAttribute') { // Assert type is very edge-cased, completely different schema $value = $subElements['expected']['value'] ?? ""; @@ -174,12 +168,4 @@ private function convertOldAssertionToNew($assertion) $newString .= " "; return $newString; } - - private function guessValueType($string) { - preg_match('/\$[a-zA-Z0-9]*/', $string, $matches); - if (isset($matches[0]) && $matches[0] == $string) { - return "variable"; - } - return "string"; - } } From f578c08e11578973355fb5d9eb4e5fe7c21e2a0a Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Wed, 4 Mar 2020 10:20:27 -0600 Subject: [PATCH 09/12] MQE-683: [Deprecation] Only use more nested assertion syntax - Safe update to upgrade script (better assert detection - Change back to TestGenerator to pass test again - Updated schema in AssertTest - Added back type to AssertContainsAttribute type (needed) --- .../TestModule/Test/AssertTest.xml | 224 +++++++++++++----- .../Test/etc/Actions/assertActions.xsd | 1 + .../Upgrade/UpdateAssertionSchema.php | 87 +++---- .../Util/TestGenerator.php | 2 +- 4 files changed, 206 insertions(+), 108 deletions(-) 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/etc/Actions/assertActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd index ca8ebcd26..84752ee7b 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd @@ -600,6 +600,7 @@ + diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index 9c8810eee..b8643f685 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -16,20 +16,6 @@ */ class UpdateAssertionSchema implements UpgradeInterface { - const OLD_ASSERTION_ATTRIBUTES = ["expected", "expectedType", "actual", "actualType"]; - - /** - * Current file being inspected, for error messaging - * @var string - */ - private $currentFile; - - /** - * Potential errors reported during replacement. - * @var array - */ - private $errors = []; - /** * Upgrades all test xml files, changing as many actions to be nested as possible * WILL NOT CATCH cases where style is a mix of old and new @@ -46,10 +32,10 @@ public function execute(InputInterface $input) $fileSystem = new Filesystem(); $testsUpdated = 0; foreach ($finder->files() as $file) { - $this->currentFile = $file->getFilename(); $contents = $file->getContents(); - // Isolate but never ... - preg_match_all('/]*\/>/', $contents, $potentialAssertions); + // Isolate but never ... , stops after finding first /> +// preg_match_all('/]*\/>/', $contents, $potentialAssertions); + preg_match_all('//', $contents, $potentialAssertions); $newAssertions = []; $index = 0; if (empty($potentialAssertions[0])) { @@ -66,23 +52,7 @@ public function execute(InputInterface $input) $testsUpdated++; } - return ("Assertion Syntax updated in {$testsUpdated} file(s).\n" . implode("\n\t", $this->errors)); - } - - /** - * Detects present of attributes in file - * - * @param string $file - * @return boolean - */ - private function detectOldAttributes($file) - { - foreach (self::OLD_ASSERTION_ATTRIBUTES as $OLD_ASSERTION_ATTRIBUTE) { - if (strpos($file->getContents(), $OLD_ASSERTION_ATTRIBUTE) !== false) { - return true; - } - } - return false; + return ("Assertion Syntax updated in {$testsUpdated} file(s).\n"); } /** @@ -91,15 +61,19 @@ private function detectOldAttributes($file) * @param string $assertion * @return string * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ private function convertOldAssertionToNew($assertion) { // assertSomething $assertType = ltrim(explode(' ', $assertion)[0], '<'); - // regex to grab values - $grabValueRegex = '/(stepKey|actual|actualType|expected|expectedType|delta|message|selector|attribute|expectedValue|before|after|remove)=(\'[^\']*\'|"[^"]*")/'; - // Make 3 arrays in $grabbedParts: + // 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 @@ -109,27 +83,33 @@ private function convertOldAssertionToNew($assertion) $sortedParts[$grabbedParts[1][$i]] = $grabbedParts[2][$i]; } - // Build new String, trim ' and " + // 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) { + } elseif (strpos($value, "'") === 0) { $value = rtrim(ltrim($value, "'"), "'"); } - // If value is empty string, trim again + // 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") { @@ -141,21 +121,28 @@ private function convertOldAssertionToNew($assertion) } } $newString .= ">\n"; - // Set type to const if it's absent - 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"; - } - // Massage subElements with data for edge case + + // Assert type is very edge-cased, completely different schema if ($assertType == 'assertElementContainsAttribute') { - // Assert type is very edge-cased, completely different schema + // 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']; - $newString .= "\t\t\t$value\n"; + // @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; diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 7cdf131b3..275c01c8f 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -1237,7 +1237,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $actionObject, $selector, $this->wrapWithDoubleQuotes($attribute), - $this->wrapWithDoubleQuotes($assertExpected) + $assertExpected ); break; case "assertEmpty": From 21e7f2d4dbd5aab4096739db6381e7406e9edf19 Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Wed, 11 Mar 2020 09:58:54 -0500 Subject: [PATCH 10/12] MQE-683: [Deprecation] Only use more nested assertion syntax - CR Fixes --- .../Test/etc/Actions/assertActions.xsd | 23 ------------------- .../Upgrade/UpdateAssertionSchema.php | 1 - 2 files changed, 24 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd index 84752ee7b..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. - - - - @@ -112,13 +96,6 @@ - - - - Assertion's Expected value. Cast by expectedType. - - - diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index b8643f685..6e834b8de 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -34,7 +34,6 @@ public function execute(InputInterface $input) foreach ($finder->files() as $file) { $contents = $file->getContents(); // Isolate but never ... , stops after finding first /> -// preg_match_all('/]*\/>/', $contents, $potentialAssertions); preg_match_all('//', $contents, $potentialAssertions); $newAssertions = []; $index = 0; From 0a2179528bd9a1b5237e5c0015cf430c86e03b19 Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Thu, 12 Mar 2020 08:54:28 -0500 Subject: [PATCH 11/12] MQE-683: [Deprecation] Only use more nested assertion syntax - Merge fixes --- .../Upgrade/UpdateAssertionSchema.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index 6e834b8de..4c3cc52b8 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -7,6 +7,7 @@ namespace Magento\FunctionalTestingFramework\Upgrade; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; @@ -21,9 +22,10 @@ class UpdateAssertionSchema implements UpgradeInterface * 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) + public function execute(InputInterface $input, OutputInterface $output) { $testsPath = $input->getArgument('path'); $finder = new Finder(); From 9357cf75c37620def3ccecfe8548733b86c291bb Mon Sep 17 00:00:00 2001 From: Kevin Kozan Date: Thu, 12 Mar 2020 09:04:07 -0500 Subject: [PATCH 12/12] MQE-683: [Deprecation] Only use more nested assertion syntax - static check fix --- .../Upgrade/UpdateAssertionSchema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php index 4c3cc52b8..09eafa483 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -21,7 +21,7 @@ class UpdateAssertionSchema implements UpgradeInterface * Upgrades all test xml files, changing as many actions to be nested as possible * WILL NOT CATCH cases where style is a mix of old and new * - * @param InputInterface $input + * @param InputInterface $input * @param OutputInterface $output * @return string */