2222use Yandex \Allure \Adapter \AllureException ;
2323use Magento \FunctionalTestingFramework \Util \Protocol \CurlTransport ;
2424use Symfony \Component \Process \Process ;
25+ use Symfony \Component \Process \Exception \ProcessTimedOutException ;
2526use Yandex \Allure \Adapter \Support \AttachmentSupport ;
2627use Magento \FunctionalTestingFramework \Exceptions \TestFrameworkException ;
2728use Magento \FunctionalTestingFramework \Config \MftfApplicationConfig ;
@@ -52,6 +53,8 @@ class MagentoWebDriver extends WebDriver
5253{
5354 use AttachmentSupport;
5455
56+ const COMMAND_CRON_RUN = 'cron:run ' ;
57+
5558 /**
5659 * List of known magento loading masks by selector
5760 *
@@ -520,13 +523,14 @@ public function scrollToTopOfPage()
520523 */
521524 public function magentoCLI ($ command , $ timeout = null , $ arguments = null )
522525 {
523- return $ this ->curlExecMagentoCLI ($ command , $ timeout , $ arguments );
524- //TODO: calling bin/magento from pipeline is timing out, needs investigation (ref: MQE-1774)
525- // try {
526- // return $this->shellExecMagentoCLI($command, $arguments);
527- // } catch (\Exception $exception) {
528- // return $this->curlExecMagentoCLI($command, $arguments);
529- // }
526+ $ magentoBinary = realpath (MAGENTO_BP . DIRECTORY_SEPARATOR . 'bin ' . DIRECTORY_SEPARATOR . 'magento ' );
527+ $ valid = $ this ->validateCommand ($ magentoBinary , $ command );
528+ // execute from shell when running tests from web root -- excludes cron jobs.
529+ if ($ valid && strpos ($ command , self ::COMMAND_CRON_RUN ) === false ) {
530+ return $ this ->shellExecMagentoCLI ($ magentoBinary , $ command , $ timeout , $ arguments );
531+ } else {
532+ return $ this ->curlExecMagentoCLI ($ command , $ timeout , $ arguments );
533+ }
530534 }
531535
532536 /**
@@ -838,6 +842,7 @@ public function makeScreenshot($name = null)
838842 /**
839843 * Takes given $command and executes it against bin/magento executable. Returns stdout output from the command.
840844 *
845+ * @param string $magentoBinary
841846 * @param string $command
842847 * @param integer $timeout
843848 * @param string $arguments
@@ -846,20 +851,41 @@ public function makeScreenshot($name = null)
846851 * @return string
847852 * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
848853 */
849- private function shellExecMagentoCLI ($ command , $ timeout , $ arguments ): string
854+ private function shellExecMagentoCLI ($ magentoBinary , $ command , $ timeout , $ arguments ): string
850855 {
851856 $ php = PHP_BINDIR ? PHP_BINDIR . DIRECTORY_SEPARATOR . 'php ' : 'php ' ;
852- $ binMagento = realpath (MAGENTO_BP . DIRECTORY_SEPARATOR . 'bin ' . DIRECTORY_SEPARATOR . 'magento ' );
853- $ command = $ php . ' -f ' . $ binMagento . ' ' . $ command . ' ' . $ arguments ;
854- $ process = new Process (escapeshellcmd ($ command ), MAGENTO_BP );
857+ $ fullCommand = $ php . ' -f ' . $ magentoBinary . ' ' . $ command . ' ' . $ arguments ;
858+ $ process = new Process (escapeshellcmd ($ fullCommand ), MAGENTO_BP );
855859 $ process ->setIdleTimeout ($ timeout );
856860 $ process ->setTimeout (0 );
857- $ exitCode = $ process ->run ();
861+ try {
862+ $ process ->run ();
863+ $ output = $ process ->getOutput ();
864+ if (!$ process ->isSuccessful ()) {
865+ $ failureOutput = $ process ->getErrorOutput ();
866+ if (!empty ($ failureOutput )) {
867+ $ output = $ failureOutput ;
868+ }
869+ }
870+ if (empty ($ output )) {
871+ $ output = "CLI did not return output. " ;
872+ }
873+
874+ } catch (ProcessTimedOutException $ exception ) {
875+ $ output = "CLI command timed out, no output available. " ;
876+
877+ }
878+
879+ if ($ this ->checkForFilePath ($ output )) {
880+ $ output = "CLI output suppressed, filepath detected in output. " ;
881+ }
882+
883+ $ exitCode = $ process ->getExitCode ();
884+
858885 if ($ exitCode !== 0 ) {
859886 throw new \RuntimeException ($ process ->getErrorOutput ());
860887 }
861-
862- return $ process ->getOutput ();
888+ return $ output ;
863889 }
864890
865891 /**
@@ -904,4 +930,40 @@ private function curlExecMagentoCLI($command, $timeout, $arguments): string
904930
905931 return $ response ;
906932 }
933+
934+ /**
935+ * Checks magento list of CLI commands for given $command. Does not check command parameters, just base command.
936+ * @param string $magentoBinary
937+ * @param string $command
938+ * @return bool
939+ */
940+ private function validateCommand ($ magentoBinary , $ command )
941+ {
942+ exec ($ magentoBinary . ' list ' , $ commandList );
943+ // Trim list of commands after first whitespace
944+ $ commandList = array_map (array ($ this , 'trimAfterWhitespace ' ), $ commandList );
945+ return in_array ($ this ->trimAfterWhitespace ($ command ), $ commandList );
946+ }
947+
948+ /**
949+ * Returns given string trimmed of everything after the first found whitespace.
950+ * @param string $string
951+ * @return string
952+ */
953+ private function trimAfterWhitespace ($ string )
954+ {
955+ return strtok ($ string , ' ' );
956+ }
957+
958+ /**
959+ * Detects file path in string.
960+ * @param string $string
961+ * @return boolean
962+ */
963+ private function checkForFilePath ($ string )
964+ {
965+ return preg_match ('/\/[\S]+\// ' , $ string );
966+ }
967+
907968}
969+
0 commit comments