diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php index 881ee69ab..e6afded68 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php @@ -12,6 +12,8 @@ use Symfony\Component\Finder\Finder; use Exception; use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Symfony\Component\Finder\SplFileInfo; +use DOMElement; /** * Class ActionGroupArgumentsCheck @@ -19,10 +21,7 @@ */ class ActionGroupArgumentsCheck implements StaticCheckInterface { - const ACTIONGROUP_XML_REGEX_PATTERN = '/).)*/mxs'; - const ACTIONGROUP_ARGUMENT_REGEX_PATTERN = '/]*name="([^"\']*)/mxs'; const ACTIONGROUP_NAME_REGEX_PATTERN = '/buildUnusedArgumentList($actionGroups[0]); - $actionGroupErrors += $this->setErrorOutput($actionGroupToArguments, $filePath); + $actionGroupToArguments = []; + $contents = $filePath->getContents(); + /** @var DOMElement $actionGroup */ + $actionGroup = $this->getActionGroupDomElement($contents); + $arguments = $this->extractActionGroupArguments($actionGroup); + $unusedArguments = $this->findUnusedArguments($arguments, $contents); + if (!empty($unusedArguments)) { + $actionGroupToArguments[$actionGroup->getAttribute('name')] = $unusedArguments; + $actionGroupErrors += $this->setErrorOutput($actionGroupToArguments, $filePath); + } } return $actionGroupErrors; } /** - * Builds array of action group => unused arguments - * @param array $actionGroups - * @return array $actionGroupToArguments + * Extract actionGroup DomElement from xml file + * @param string $contents + * @return \DOMElement */ - private function buildUnusedArgumentList($actionGroups) + public function getActionGroupDomElement($contents) { - $actionGroupToArguments = []; + $domDocument = new \DOMDocument(); + $domDocument->loadXML($contents); + return $domDocument->getElementsByTagName('actionGroup')[0]; + } - foreach ($actionGroups as $actionGroupXml) { - preg_match(self::ACTIONGROUP_NAME_REGEX_PATTERN, $actionGroupXml, $actionGroupName); - $unusedArguments = $this->findUnusedArguments($actionGroupXml); - if (!empty($unusedArguments)) { - $actionGroupToArguments[$actionGroupName[1]] = $unusedArguments; + /** + * Get list of action group arguments declared in an action group + * @param \DOMElement $actionGroup + * @return array $arguments + */ + public function extractActionGroupArguments($actionGroup) + { + $arguments = []; + $argumentsNodes = $actionGroup->getElementsByTagName('arguments'); + if ($argumentsNodes->length > 0) { + $argumentNodes = $argumentsNodes[0]->getElementsByTagName('argument'); + foreach ($argumentNodes as $argumentNode) { + $arguments[] = $argumentNode->getAttribute('name'); } } - return $actionGroupToArguments; + return $arguments; } /** * Returns unused arguments in an action group - * @param string $actionGroupXml + * @param array $arguments + * @param string $contents * @return array */ - private function findUnusedArguments($actionGroupXml) + public function findUnusedArguments($arguments, $contents) { $unusedArguments = []; - - preg_match_all(self::ACTIONGROUP_ARGUMENT_REGEX_PATTERN, $actionGroupXml, $arguments); - preg_match(self::ACTIONGROUP_NAME_REGEX_PATTERN, $actionGroupXml, $actionGroupName); + preg_match(self::ACTIONGROUP_NAME_REGEX_PATTERN, $contents, $actionGroupName); $validActionGroup = false; try { $actionGroup = ActionGroupObjectHandler::getInstance()->getObject($actionGroupName[1]); @@ -149,18 +165,18 @@ private function findUnusedArguments($actionGroupXml) return $unusedArguments; } - foreach ($arguments[1] as $argument) { + foreach ($arguments as $argument) { //pattern to match all argument references $patterns = [ '(\{{2}' . $argument . '(\.[a-zA-Z0-9_\[\]\(\).,\'\/ ]+)?}{2})', '([(,\s\'$$]' . $argument . '(\.[a-zA-Z0-9_$\[\]]+)?[),\s\'])' ]; // matches entity references - if (preg_match($patterns[0], $actionGroupXml)) { + if (preg_match($patterns[0], $contents)) { continue; } //matches parametrized references - if (preg_match($patterns[1], $actionGroupXml)) { + if (preg_match($patterns[1], $contents)) { continue; } //for extending action groups, exclude arguments that are also defined in parent action group @@ -196,8 +212,8 @@ private function isParentActionGroupArgument($argument, $actionGroup) /** * Builds and returns error output for violating references * - * @param array $actionGroupToArguments - * @param string $path + * @param array $actionGroupToArguments + * @param SplFileInfo $path * @return mixed */ private function setErrorOutput($actionGroupToArguments, $path) diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/RemoveUnusedArguments.php b/src/Magento/FunctionalTestingFramework/Upgrade/RemoveUnusedArguments.php new file mode 100644 index 000000000..ced1042ad --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Upgrade/RemoveUnusedArguments.php @@ -0,0 +1,65 @@ +/s"; + + /** + * Updates all actionGroup xml files + * + * @param InputInterface $input + * @param OutputInterface $output + * @return string + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $scriptUtil = new ScriptUtil(); + $testPaths[] = $input->getArgument('path'); + if (empty($testPaths[0])) { + $testPaths = $scriptUtil->getAllModulePaths(); + } + $xmlFiles = $scriptUtil->getModuleXmlFilesByScope($testPaths, 'ActionGroup'); + $actionGroupsUpdated = 0; + $fileSystem = new Filesystem(); + foreach ($xmlFiles as $file) { + $contents = $file->getContents(); + $argumentsCheck = new ActionGroupArgumentsCheck(); + /** @var DOMElement $actionGroup */ + $actionGroup = $argumentsCheck->getActionGroupDomElement($contents); + $allArguments = $argumentsCheck->extractActionGroupArguments($actionGroup); + $unusedArguments = $argumentsCheck->findUnusedArguments($allArguments, $contents); + if (empty($unusedArguments)) { + continue; + } + //Remove block if all arguments are unused + if (empty(array_diff($allArguments, $unusedArguments))) { + $contents = preg_replace(self::ARGUMENTS_BLOCK_REGEX_PATTERN, '', $contents); + } else { + foreach ($unusedArguments as $argument) { + $argumentRegexPattern = "/\s*/"; + $contents = preg_replace($argumentRegexPattern, '', $contents); + } + } + $fileSystem->dumpFile($file->getRealPath(), $contents); + $actionGroupsUpdated++; + } + return "Removed unused action group arguments from {$actionGroupsUpdated} file(s)."; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php index 6293b589b..cf2aabe2d 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php @@ -28,6 +28,7 @@ class UpgradeScriptList implements UpgradeScriptListInterface public function __construct(array $scripts = []) { $this->scripts = [ + 'removeUnusedArguments' => new RemoveUnusedArguments(), 'upgradeTestSchema' => new UpdateTestSchemaPaths(), 'upgradeAssertionSchema' => new UpdateAssertionSchema(), 'renameMetadataFiles' => new RenameMetadataFiles(),