1616use Codeception \Util \Uri ;
1717use Magento \FunctionalTestingFramework \DataGenerator \Handlers \CredentialStore ;
1818use Magento \FunctionalTestingFramework \DataGenerator \Persist \Curl \WebapiExecutor ;
19- use Magento \FunctionalTestingFramework \Util \Protocol \CurlTransport ;
2019use Magento \FunctionalTestingFramework \Util \Protocol \CurlInterface ;
2120use Magento \FunctionalTestingFramework \Util \ConfigSanitizerUtil ;
2221use Yandex \Allure \Adapter \AllureException ;
22+ use Magento \FunctionalTestingFramework \Util \Protocol \CurlTransport ;
23+ use Symfony \Component \Process \Process ;
2324use Yandex \Allure \Adapter \Support \AttachmentSupport ;
2425use Magento \FunctionalTestingFramework \Exceptions \TestFrameworkException ;
2526
@@ -49,14 +50,15 @@ class MagentoWebDriver extends WebDriver
4950
5051 /**
5152 * List of known magento loading masks by selector
53+ *
5254 * @var array
5355 */
5456 public static $ loadingMasksLocators = [
5557 '//div[contains(@class, "loading-mask")] ' ,
5658 '//div[contains(@class, "admin_data-grid-loading-mask")] ' ,
5759 '//div[contains(@class, "admin__data-grid-loading-mask")] ' ,
5860 '//div[contains(@class, "admin__form-loading-mask")] ' ,
59- '//div[@data-role="spinner"] '
61+ '//div[@data-role="spinner"] ' ,
6062 ];
6163
6264 /**
@@ -69,7 +71,7 @@ class MagentoWebDriver extends WebDriver
6971 'backend_name ' ,
7072 'username ' ,
7173 'password ' ,
72- 'browser '
74+ 'browser ' ,
7375 ];
7476
7577 /**
@@ -116,6 +118,7 @@ class MagentoWebDriver extends WebDriver
116118
117119 /**
118120 * Sanitizes config, then initializes using parent.
121+ *
119122 * @return void
120123 */
121124 public function _initialize ()
@@ -139,6 +142,7 @@ public function _resetConfig()
139142
140143 /**
141144 * Remap parent::_after, called in TestContextExtension
145+ *
142146 * @param TestInterface $test
143147 * @return void
144148 */
@@ -149,9 +153,10 @@ public function _runAfter(TestInterface $test)
149153
150154 /**
151155 * Override parent::_after to do nothing.
152- * @return void
156+ *
153157 * @param TestInterface $test
154158 * @SuppressWarnings(PHPMD)
159+ * @return void
155160 */
156161 public function _after (TestInterface $ test )
157162 {
@@ -161,9 +166,9 @@ public function _after(TestInterface $test)
161166 /**
162167 * Returns URL of a host.
163168 *
164- * @api
165169 * @return mixed
166170 * @throws ModuleConfigException
171+ * @api
167172 */
168173 public function _getUrl ()
169174 {
@@ -173,22 +178,24 @@ public function _getUrl()
173178 "Module connection failure. The URL for client can't bre retrieved "
174179 );
175180 }
181+
176182 return $ this ->config ['url ' ];
177183 }
178184
179185 /**
180186 * Uri of currently opened page.
181187 *
182188 * @return string
183- * @api
184189 * @throws ModuleException
190+ * @api
185191 */
186192 public function _getCurrentUri ()
187193 {
188194 $ url = $ this ->webDriver ->getCurrentURL ();
189195 if ($ url == 'about:blank ' ) {
190196 throw new ModuleException ($ this , 'Current url is blank, no page was opened ' );
191197 }
198+
192199 return Uri::retrieveUri ($ url );
193200 }
194201
@@ -257,6 +264,7 @@ public function grabFromCurrentUrl($regex = null)
257264 if (!isset ($ matches [1 ])) {
258265 $ this ->fail ("Nothing to grab. A regex parameter with a capture group is required. Ex: '/(foo)(bar)/' " );
259266 }
267+
260268 return $ matches [1 ];
261269 }
262270
@@ -326,13 +334,13 @@ public function closeAdminNotification()
326334 * @param string $select
327335 * @param array $options
328336 * @param boolean $requireAction
329- * @throws \Exception
330337 * @return void
338+ * @throws \Exception
331339 */
332340 public function searchAndMultiSelectOption ($ select , array $ options , $ requireAction = false )
333341 {
334- $ selectDropdown = $ select . ' .action-select.admin__action-multiselect ' ;
335- $ selectSearchText = $ select
342+ $ selectDropdown = $ select . ' .action-select.admin__action-multiselect ' ;
343+ $ selectSearchText = $ select
336344 . ' .admin__action-multiselect-search-wrap>input[data-role="advanced-select-text"] ' ;
337345 $ selectSearchResult = $ select . ' .admin__action-multiselect-label>span ' ;
338346
@@ -355,8 +363,8 @@ public function searchAndMultiSelectOption($select, array $options, $requireActi
355363 * @param string $selectSearchTextField
356364 * @param string $selectSearchResult
357365 * @param string[] $options
358- * @throws \Exception
359366 * @return void
367+ * @throws \Exception
360368 */
361369 public function selectMultipleOptions ($ selectSearchTextField , $ selectSearchResult , array $ options )
362370 {
@@ -393,8 +401,8 @@ public function waitForAjaxLoad($timeout = null)
393401 * Wait for all JavaScript to finish executing.
394402 *
395403 * @param integer $timeout
396- * @throws \Exception
397404 * @return void
405+ * @throws \Exception
398406 */
399407 public function waitForPageLoad ($ timeout = null )
400408 {
@@ -409,8 +417,8 @@ public function waitForPageLoad($timeout = null)
409417 * Wait for all visible loading masks to disappear. Gets all elements by mask selector, then loops over them.
410418 *
411419 * @param integer $timeout
412- * @throws \Exception
413420 * @return void
421+ * @throws \Exception
414422 */
415423 public function waitForLoadingMaskToDisappear ($ timeout = null )
416424 {
@@ -438,6 +446,7 @@ public function formatMoney(float $money, $locale = 'en_US.UTF-8')
438446 $ this ->mResetLocale ();
439447 $ prefix = substr ($ money , 0 , 1 );
440448 $ number = substr ($ money , 1 );
449+
441450 return ['prefix ' => $ prefix , 'number ' => $ number ];
442451 }
443452
@@ -450,6 +459,7 @@ public function formatMoney(float $money, $locale = 'en_US.UTF-8')
450459 public function parseFloat ($ floatString )
451460 {
452461 $ floatString = str_replace (', ' , '' , $ floatString );
462+
453463 return floatval ($ floatString );
454464 }
455465
@@ -471,6 +481,7 @@ public function mSetLocale(int $category, $locale)
471481
472482 /**
473483 * Reset Locale setting.
484+ *
474485 * @return void
475486 */
476487 public function mResetLocale ()
@@ -485,6 +496,7 @@ public function mResetLocale()
485496
486497 /**
487498 * Scroll to the Top of the Page.
499+ *
488500 * @return void
489501 */
490502 public function scrollToTopOfPage ()
@@ -493,51 +505,36 @@ public function scrollToTopOfPage()
493505 }
494506
495507 /**
496- * Takes given $command and executes it against exposed MTF CLI entry point. Returns response from server.
508+ * Takes given $command and executes it against bin/magento or custom exposed entrypoint. Returns command output.
509+ *
497510 * @param string $command
498511 * @param string $arguments
499- * @throws TestFrameworkException
500512 * @return string
513+ * @throws TestFrameworkException
501514 */
502515 public function magentoCLI ($ command , $ arguments = null )
503516 {
504- // Remove index.php if it's present in url
505- $ baseUrl = rtrim (
506- str_replace ('index.php ' , '' , rtrim ($ this ->config ['url ' ], '/ ' )),
507- '/ '
508- );
509- $ apiURL = $ baseUrl . '/ ' . ltrim (getenv ('MAGENTO_CLI_COMMAND_PATH ' ), '/ ' );
510-
511- $ restExecutor = new WebapiExecutor ();
512- $ executor = new CurlTransport ();
513- $ executor ->write (
514- $ apiURL ,
515- [
516- 'token ' => $ restExecutor ->getAuthToken (),
517- getenv ('MAGENTO_CLI_COMMAND_PARAMETER ' ) => $ command ,
518- 'arguments ' => $ arguments
519- ],
520- CurlInterface::POST ,
521- []
522- );
523- $ response = $ executor ->read ();
524- $ restExecutor ->close ();
525- $ executor ->close ();
526- return $ response ;
517+ try {
518+ return $ this ->shellExecMagentoCLI ($ command , $ arguments );
519+ } catch (\Exception $ exception ) {
520+ return $ this ->curlExecMagentoCLI ($ command , $ arguments );
521+ }
527522 }
528523
529524 /**
530525 * Runs DELETE request to delete a Magento entity against the url given.
526+ *
531527 * @param string $url
532- * @throws TestFrameworkException
533528 * @return string
529+ * @throws TestFrameworkException
534530 */
535531 public function deleteEntityByUrl ($ url )
536532 {
537533 $ executor = new WebapiExecutor (null );
538534 $ executor ->write ($ url , [], CurlInterface::DELETE , []);
539535 $ response = $ executor ->read ();
540536 $ executor ->close ();
537+
541538 return $ response ;
542539 }
543540
@@ -547,8 +544,8 @@ public function deleteEntityByUrl($url)
547544 * @param string $selector
548545 * @param string $dependentSelector
549546 * @param boolean $visible
550- * @throws \Exception
551547 * @return void
548+ * @throws \Exception
552549 */
553550 public function conditionalClick ($ selector , $ dependentSelector , $ visible )
554551 {
@@ -603,6 +600,7 @@ public function assertElementContainsAttribute($selector, $attribute, $value)
603600
604601 /**
605602 * Sets current test to the given test, and resets test failure artifacts to null
603+ *
606604 * @param TestInterface $test
607605 * @return void
608606 */
@@ -617,6 +615,7 @@ public function _before(TestInterface $test)
617615
618616 /**
619617 * Override for codeception's default dragAndDrop to include offset options.
618+ *
620619 * @param string $source
621620 * @param string $target
622621 * @param integer $xOffset
@@ -711,6 +710,7 @@ public function _failed(TestInterface $test, $fail)
711710
712711 /**
713712 * Function which saves a screenshot of the current stat of the browser
713+ *
714714 * @return void
715715 */
716716 public function saveScreenshot ()
@@ -730,8 +730,8 @@ public function saveScreenshot()
730730 * Go to a page and wait for ajax requests to finish
731731 *
732732 * @param string $page
733- * @throws \Exception
734733 * @return void
734+ * @throws \Exception
735735 */
736736 public function amOnPage ($ page )
737737 {
@@ -743,8 +743,8 @@ public function amOnPage($page)
743743 * Turn Readiness check on or off
744744 *
745745 * @param boolean $check
746- * @throws \Exception
747746 * @return void
747+ * @throws \Exception
748748 */
749749 public function skipReadinessCheck ($ check )
750750 {
@@ -787,6 +787,7 @@ private function getJsErrors()
787787 $ errors .= "\n" . $ jsError ;
788788 }
789789 }
790+
790791 return $ errors ;
791792 }
792793
@@ -824,4 +825,65 @@ public function makeScreenshot($name = null)
824825 $ this ->debug ("Screenshot saved to $ screenName " );
825826 AllureHelper::addAttachmentToCurrentStep ($ screenName , 'Screenshot ' );
826827 }
828+
829+ /**
830+ * Takes given $command and executes it against bin/magento executable. Returns stdout output from the command.
831+ *
832+ * @param string $command
833+ * @param string $arguments
834+ *
835+ * @throws \RuntimeException
836+ * @return string
837+ */
838+ private function shellExecMagentoCLI ($ command , $ arguments ): string
839+ {
840+ $ php = PHP_BINDIR ? PHP_BINDIR . DIRECTORY_SEPARATOR . 'php ' : 'php ' ;
841+ $ binMagento = realpath (MAGENTO_BP . DIRECTORY_SEPARATOR . 'bin ' . DIRECTORY_SEPARATOR . 'magento ' );
842+ $ command = $ php . ' -f ' . $ binMagento . ' ' . $ command . ' ' . $ arguments ;
843+ $ process = new Process (escapeshellcmd ($ command ), MAGENTO_BP );
844+ $ process ->setIdleTimeout (60 );
845+ $ process ->setTimeout (0 );
846+ $ exitCode = $ process ->run ();
847+ if ($ exitCode !== 0 ) {
848+ throw new \RuntimeException ($ process ->getErrorOutput ());
849+ }
850+
851+ return $ process ->getOutput ();
852+ }
853+
854+ /**
855+ * Takes given $command and executes it against exposed MTF CLI entry point. Returns response from server.
856+ *
857+ * @param string $command
858+ * @param string $arguments
859+ * @return string
860+ * @throws TestFrameworkException
861+ */
862+ private function curlExecMagentoCLI ($ command , $ arguments ): string
863+ {
864+ // Remove index.php if it's present in url
865+ $ baseUrl = rtrim (
866+ str_replace ('index.php ' , '' , rtrim ($ this ->config ['url ' ], '/ ' )),
867+ '/ '
868+ );
869+ $ apiURL = $ baseUrl . '/ ' . ltrim (getenv ('MAGENTO_CLI_COMMAND_PATH ' ), '/ ' );
870+
871+ $ restExecutor = new WebapiExecutor ();
872+ $ executor = new CurlTransport ();
873+ $ executor ->write (
874+ $ apiURL ,
875+ [
876+ 'token ' => $ restExecutor ->getAuthToken (),
877+ getenv ('MAGENTO_CLI_COMMAND_PARAMETER ' ) => $ command ,
878+ 'arguments ' => $ arguments ,
879+ ],
880+ CurlInterface::POST ,
881+ []
882+ );
883+ $ response = $ executor ->read ();
884+ $ restExecutor ->close ();
885+ $ executor ->close ();
886+
887+ return $ response ;
888+ }
827889}
0 commit comments