diff --git a/dev/tests/static/framework/Magento/TestFramework/Utility/AddedFiles.php b/dev/tests/static/framework/Magento/TestFramework/Utility/AddedFiles.php new file mode 100644 index 0000000000000..4afeda3a035eb --- /dev/null +++ b/dev/tests/static/framework/Magento/TestFramework/Utility/AddedFiles.php @@ -0,0 +1,35 @@ +classNameExtractor = new ClassNameExtractor(); + } + + /** + * Get list of classes name which are subclasses of mentioned class. + * + * @param array $fileList + * @param string $parent + * @param bool $asDataSet + * + * @return array + * @throws \ReflectionException + */ + public function getClassesWhichAreChildrenOf(array $fileList, string $parent, bool $asDataSet = true): array + { + $found = []; + + foreach ($fileList as $file) { + $name = $asDataSet ? $file[0] : $file; + $class = $this->classNameExtractor->getNameWithNamespace(file_get_contents($name)); + + if ($class) { + $classReflection = new \ReflectionClass($class); + if ($classReflection->isSubclassOf($parent)) { + $found[] = $class; + } + } + } + + return $found; + } +} diff --git a/dev/tests/static/framework/Magento/TestFramework/Utility/FilesSearch.php b/dev/tests/static/framework/Magento/TestFramework/Utility/FilesSearch.php new file mode 100644 index 0000000000000..0ec8124496d1d --- /dev/null +++ b/dev/tests/static/framework/Magento/TestFramework/Utility/FilesSearch.php @@ -0,0 +1,48 @@ +childrenClassesSearch = new ChildrenClassesSearch(); + } + + public function testChildrenSearch(): void + { + $files = [ + __DIR__ . '/ChildrenClassesSearch/A.php', + __DIR__ . '/ChildrenClassesSearch/B.php', + __DIR__ . '/ChildrenClassesSearch/C.php', + __DIR__ . '/ChildrenClassesSearch/D.php', + __DIR__ . '/ChildrenClassesSearch/E.php', + __DIR__ . '/ChildrenClassesSearch/F.php', + __DIR__ . '/ChildrenClassesSearch/ZInterface.php', + ]; + + $found = $this->childrenClassesSearch->getClassesWhichAreChildrenOf( + $files, + A::class, + false + ); + + $expected = [ + B::class, + E::class, + F::class + ]; + + $this->assertSame($expected, $found); + } +} diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FilesSearchTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FilesSearchTest.php new file mode 100644 index 0000000000000..7b27dde3b0bf4 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FilesSearchTest.php @@ -0,0 +1,53 @@ +assertSame($files, $expected); + } + + /** + * Test callblack function in case when files with lists did not found. + */ + public function testGetEmptyList(): void + { + $pattern = 'zzz.txt'; + + $files = FilesSearch::getFilesFromListFile(__DIR__, $pattern, function () { + return ['1', '2', '3']; + }); + + $expected = [ + BP . '/1', + BP . '/2', + BP . '/3' + ]; + + $this->assertSame($files, $expected); + } +} diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/_files/changed_files_some_name_test.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/_files/changed_files_some_name_test.txt new file mode 100644 index 0000000000000..816f4b32c9361 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/_files/changed_files_some_name_test.txt @@ -0,0 +1,3 @@ +app/code/Magento/Cms/Block/Block.php +app/code/Magento/Cms/Api/BlockRepositoryInterface.php +app/code/Magento/Cms/Observer/NoCookiesObserver.php diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/Magento/Framework/App/Action/AbstractActionTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/Magento/Framework/App/Action/AbstractActionTest.php new file mode 100644 index 0000000000000..69050c3c51895 --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/Magento/Framework/App/Action/AbstractActionTest.php @@ -0,0 +1,85 @@ +childrenClassesSearch = new ChildrenClassesSearch(); + $this->fileUtilities = Files::init(); + } + + /** + * Test newly created controllers do not extend deprecated AbstractAction. + * + * @throws \ReflectionException + */ + public function testNewControllersDoNotExtendAbstractAction(): void + { + $files = $this->getTestFiles(); + + $found = $this->childrenClassesSearch->getClassesWhichAreChildrenOf($files, AbstractAction::class); + + $this->assertEmpty( + $found, + "The following new controller(s) extend " . AbstractAction::class . "\r\n" + . "All new controller classes must implement " . ActionInterface::class . " instead.\r\n" + . print_r($found, true) + ); + } + + /** + * Provide files for test. + * + * @return array + */ + private function getTestFiles(): array + { + $phpFiles = AddedFiles::getAddedFilesList($this->getChangedFilesBaseDir()); + + $phpFiles = Files::composeDataSets($phpFiles); + $fileTypes = Files::INCLUDE_APP_CODE | Files::INCLUDE_LIBS | Files::AS_DATA_SET; + return array_intersect_key($phpFiles, $this->fileUtilities->getPhpFiles($fileTypes)); + } + + /** + * Returns base directory for generated lists. + * + * @return string + */ + private function getChangedFilesBaseDir(): string + { + return BP . DIRECTORY_SEPARATOR . 'dev' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'static' . + DIRECTORY_SEPARATOR . 'testsuite' . DIRECTORY_SEPARATOR . 'Magento' . DIRECTORY_SEPARATOR . 'Test'; + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php index 324753b4bd4ec..ad91025448579 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php @@ -14,6 +14,8 @@ use Magento\TestFramework\CodingStandard\Tool\CopyPasteDetector; use Magento\TestFramework\CodingStandard\Tool\PhpCompatibility; use Magento\TestFramework\CodingStandard\Tool\PhpStan; +use Magento\TestFramework\Utility\AddedFiles; +use Magento\TestFramework\Utility\FilesSearch; use PHPMD\TextUI\Command; /** @@ -113,8 +115,8 @@ public static function getWhitelist( */ private static function getChangedFilesList($changedFilesBaseDir) { - return self::getFilesFromListFile( - $changedFilesBaseDir, + return FilesSearch::getFilesFromListFile( + $changedFilesBaseDir ?: self::getChangedFilesBaseDir(), 'changed_files*', function () { // if no list files, probably, this is the dev environment @@ -128,65 +130,6 @@ function () { ); } - /** - * This method loads list of added files. - * - * @param string $changedFilesBaseDir - * @return string[] - */ - private static function getAddedFilesList($changedFilesBaseDir) - { - return self::getFilesFromListFile( - $changedFilesBaseDir, - 'changed_files*.added.*', - function () { - // if no list files, probably, this is the dev environment - // phpcs:ignore Generic.PHP.NoSilencedErrors,Magento2.Security.InsecureFunction - @exec('git diff --cached --name-only --diff-filter=A', $addedFiles); - return $addedFiles; - } - ); - } - - /** - * Read files from generated lists. - * - * @param string $listsBaseDir - * @param string $listFilePattern - * @param callable $noListCallback - * @return string[] - */ - private static function getFilesFromListFile($listsBaseDir, $listFilePattern, $noListCallback) - { - $filesDefinedInList = []; - - $globFilesListPattern = ($listsBaseDir ?: self::getChangedFilesBaseDir()) - . '/_files/' . $listFilePattern; - $listFiles = glob($globFilesListPattern); - if (!empty($listFiles)) { - foreach ($listFiles as $listFile) { - // phpcs:ignore Magento2.Performance.ForeachArrayMerge.ForeachArrayMerge - $filesDefinedInList = array_merge( - $filesDefinedInList, - file($listFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) - ); - } - } else { - $filesDefinedInList = call_user_func($noListCallback); - } - - array_walk( - $filesDefinedInList, - function (&$file) { - $file = BP . '/' . $file; - } - ); - - $filesDefinedInList = array_values(array_unique($filesDefinedInList)); - - return $filesDefinedInList; - } - /** * Filter list of files. * @@ -427,7 +370,7 @@ public function testCopyPaste() */ public function testStrictTypes() { - $changedFiles = self::getAddedFilesList(''); + $changedFiles = AddedFiles::getAddedFilesList(self::getChangedFilesBaseDir()); try { $blackList = Files::init()->readLists(