Skip to content

Allow the webdriver to directly call upon the 'bin/magento' executable #343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 23, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 103 additions & 41 deletions src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
use Codeception\Util\Uri;
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore;
use Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl\WebapiExecutor;
use Magento\FunctionalTestingFramework\Util\Protocol\CurlTransport;
use Magento\FunctionalTestingFramework\Util\Protocol\CurlInterface;
use Magento\FunctionalTestingFramework\Util\ConfigSanitizerUtil;
use Yandex\Allure\Adapter\AllureException;
use Magento\FunctionalTestingFramework\Util\Protocol\CurlTransport;
use Symfony\Component\Process\Process;
use Yandex\Allure\Adapter\Support\AttachmentSupport;
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;

Expand Down Expand Up @@ -49,14 +50,15 @@ class MagentoWebDriver extends WebDriver

/**
* List of known magento loading masks by selector
*
* @var array
*/
public static $loadingMasksLocators = [
'//div[contains(@class, "loading-mask")]',
'//div[contains(@class, "admin_data-grid-loading-mask")]',
'//div[contains(@class, "admin__data-grid-loading-mask")]',
'//div[contains(@class, "admin__form-loading-mask")]',
'//div[@data-role="spinner"]'
'//div[@data-role="spinner"]',
];

/**
Expand All @@ -69,7 +71,7 @@ class MagentoWebDriver extends WebDriver
'backend_name',
'username',
'password',
'browser'
'browser',
];

/**
Expand Down Expand Up @@ -116,6 +118,7 @@ class MagentoWebDriver extends WebDriver

/**
* Sanitizes config, then initializes using parent.
*
* @return void
*/
public function _initialize()
Expand All @@ -139,6 +142,7 @@ public function _resetConfig()

/**
* Remap parent::_after, called in TestContextExtension
*
* @param TestInterface $test
* @return void
*/
Expand All @@ -149,9 +153,10 @@ public function _runAfter(TestInterface $test)

/**
* Override parent::_after to do nothing.
* @return void
*
* @param TestInterface $test
* @SuppressWarnings(PHPMD)
* @return void
*/
public function _after(TestInterface $test)
{
Expand All @@ -161,9 +166,9 @@ public function _after(TestInterface $test)
/**
* Returns URL of a host.
*
* @api
* @return mixed
* @throws ModuleConfigException
* @api
*/
public function _getUrl()
{
Expand All @@ -173,22 +178,24 @@ public function _getUrl()
"Module connection failure. The URL for client can't bre retrieved"
);
}

return $this->config['url'];
}

/**
* Uri of currently opened page.
*
* @return string
* @api
* @throws ModuleException
* @api
*/
public function _getCurrentUri()
{
$url = $this->webDriver->getCurrentURL();
if ($url == 'about:blank') {
throw new ModuleException($this, 'Current url is blank, no page was opened');
}

return Uri::retrieveUri($url);
}

Expand Down Expand Up @@ -257,6 +264,7 @@ public function grabFromCurrentUrl($regex = null)
if (!isset($matches[1])) {
$this->fail("Nothing to grab. A regex parameter with a capture group is required. Ex: '/(foo)(bar)/'");
}

return $matches[1];
}

Expand Down Expand Up @@ -326,13 +334,13 @@ public function closeAdminNotification()
* @param string $select
* @param array $options
* @param boolean $requireAction
* @throws \Exception
* @return void
* @throws \Exception
*/
public function searchAndMultiSelectOption($select, array $options, $requireAction = false)
{
$selectDropdown = $select . ' .action-select.admin__action-multiselect';
$selectSearchText = $select
$selectDropdown = $select . ' .action-select.admin__action-multiselect';
$selectSearchText = $select
. ' .admin__action-multiselect-search-wrap>input[data-role="advanced-select-text"]';
$selectSearchResult = $select . ' .admin__action-multiselect-label>span';

Expand All @@ -355,8 +363,8 @@ public function searchAndMultiSelectOption($select, array $options, $requireActi
* @param string $selectSearchTextField
* @param string $selectSearchResult
* @param string[] $options
* @throws \Exception
* @return void
* @throws \Exception
*/
public function selectMultipleOptions($selectSearchTextField, $selectSearchResult, array $options)
{
Expand Down Expand Up @@ -393,8 +401,8 @@ public function waitForAjaxLoad($timeout = null)
* Wait for all JavaScript to finish executing.
*
* @param integer $timeout
* @throws \Exception
* @return void
* @throws \Exception
*/
public function waitForPageLoad($timeout = null)
{
Expand All @@ -409,8 +417,8 @@ public function waitForPageLoad($timeout = null)
* Wait for all visible loading masks to disappear. Gets all elements by mask selector, then loops over them.
*
* @param integer $timeout
* @throws \Exception
* @return void
* @throws \Exception
*/
public function waitForLoadingMaskToDisappear($timeout = null)
{
Expand Down Expand Up @@ -438,6 +446,7 @@ public function formatMoney(float $money, $locale = 'en_US.UTF-8')
$this->mResetLocale();
$prefix = substr($money, 0, 1);
$number = substr($money, 1);

return ['prefix' => $prefix, 'number' => $number];
}

Expand All @@ -450,6 +459,7 @@ public function formatMoney(float $money, $locale = 'en_US.UTF-8')
public function parseFloat($floatString)
{
$floatString = str_replace(',', '', $floatString);

return floatval($floatString);
}

Expand All @@ -471,6 +481,7 @@ public function mSetLocale(int $category, $locale)

/**
* Reset Locale setting.
*
* @return void
*/
public function mResetLocale()
Expand All @@ -485,6 +496,7 @@ public function mResetLocale()

/**
* Scroll to the Top of the Page.
*
* @return void
*/
public function scrollToTopOfPage()
Expand All @@ -493,51 +505,36 @@ public function scrollToTopOfPage()
}

/**
* Takes given $command and executes it against exposed MTF CLI entry point. Returns response from server.
* Takes given $command and executes it against bin/magento or custom exposed entrypoint. Returns command output.
*
* @param string $command
* @param string $arguments
* @throws TestFrameworkException
* @return string
* @throws TestFrameworkException
*/
public function magentoCLI($command, $arguments = null)
{
// Remove index.php if it's present in url
$baseUrl = rtrim(
str_replace('index.php', '', rtrim($this->config['url'], '/')),
'/'
);
$apiURL = $baseUrl . '/' . ltrim(getenv('MAGENTO_CLI_COMMAND_PATH'), '/');

$restExecutor = new WebapiExecutor();
$executor = new CurlTransport();
$executor->write(
$apiURL,
[
'token' => $restExecutor->getAuthToken(),
getenv('MAGENTO_CLI_COMMAND_PARAMETER') => $command,
'arguments' => $arguments
],
CurlInterface::POST,
[]
);
$response = $executor->read();
$restExecutor->close();
$executor->close();
return $response;
try {
return $this->shellExecMagentoCLI($command, $arguments);
} catch (\Exception $exception) {
return $this->curlExecMagentoCLI($command, $arguments);
}
}

/**
* Runs DELETE request to delete a Magento entity against the url given.
*
* @param string $url
* @throws TestFrameworkException
* @return string
* @throws TestFrameworkException
*/
public function deleteEntityByUrl($url)
{
$executor = new WebapiExecutor(null);
$executor->write($url, [], CurlInterface::DELETE, []);
$response = $executor->read();
$executor->close();

return $response;
}

Expand All @@ -547,8 +544,8 @@ public function deleteEntityByUrl($url)
* @param string $selector
* @param string $dependentSelector
* @param boolean $visible
* @throws \Exception
* @return void
* @throws \Exception
*/
public function conditionalClick($selector, $dependentSelector, $visible)
{
Expand Down Expand Up @@ -603,6 +600,7 @@ public function assertElementContainsAttribute($selector, $attribute, $value)

/**
* Sets current test to the given test, and resets test failure artifacts to null
*
* @param TestInterface $test
* @return void
*/
Expand All @@ -617,6 +615,7 @@ public function _before(TestInterface $test)

/**
* Override for codeception's default dragAndDrop to include offset options.
*
* @param string $source
* @param string $target
* @param integer $xOffset
Expand Down Expand Up @@ -711,6 +710,7 @@ public function _failed(TestInterface $test, $fail)

/**
* Function which saves a screenshot of the current stat of the browser
*
* @return void
*/
public function saveScreenshot()
Expand All @@ -730,8 +730,8 @@ public function saveScreenshot()
* Go to a page and wait for ajax requests to finish
*
* @param string $page
* @throws \Exception
* @return void
* @throws \Exception
*/
public function amOnPage($page)
{
Expand All @@ -743,8 +743,8 @@ public function amOnPage($page)
* Turn Readiness check on or off
*
* @param boolean $check
* @throws \Exception
* @return void
* @throws \Exception
*/
public function skipReadinessCheck($check)
{
Expand Down Expand Up @@ -787,6 +787,7 @@ private function getJsErrors()
$errors .= "\n" . $jsError;
}
}

return $errors;
}

Expand Down Expand Up @@ -824,4 +825,65 @@ public function makeScreenshot($name = null)
$this->debug("Screenshot saved to $screenName");
AllureHelper::addAttachmentToCurrentStep($screenName, 'Screenshot');
}

/**
* Takes given $command and executes it against bin/magento executable. Returns stdout output from the command.
*
* @param string $command
* @param string $arguments
*
* @throws \RuntimeException
* @return string
*/
private function shellExecMagentoCLI($command, $arguments): string
{
$php = PHP_BINDIR ? PHP_BINDIR . DIRECTORY_SEPARATOR. 'php' : 'php';
$binMagento = realpath(MAGENTO_BP . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'magento');
$command = $php . ' -f ' . $binMagento . ' ' . $command . ' ' . $arguments;
$process = new Process(escapeshellcmd($command), MAGENTO_BP);
$process->setIdleTimeout(60);
$process->setTimeout(0);
$exitCode = $process->run();
if ($exitCode !== 0) {
throw new \RuntimeException($process->getErrorOutput());
}

return $process->getOutput();
}

/**
* Takes given $command and executes it against exposed MTF CLI entry point. Returns response from server.
*
* @param string $command
* @param string $arguments
* @return string
* @throws TestFrameworkException
*/
private function curlExecMagentoCLI($command, $arguments): string
{
// Remove index.php if it's present in url
$baseUrl = rtrim(
str_replace('index.php', '', rtrim($this->config['url'], '/')),
'/'
);
$apiURL = $baseUrl . '/' . ltrim(getenv('MAGENTO_CLI_COMMAND_PATH'), '/');

$restExecutor = new WebapiExecutor();
$executor = new CurlTransport();
$executor->write(
$apiURL,
[
'token' => $restExecutor->getAuthToken(),
getenv('MAGENTO_CLI_COMMAND_PARAMETER') => $command,
'arguments' => $arguments,
],
CurlInterface::POST,
[]
);
$response = $executor->read();
$restExecutor->close();
$executor->close();

return $response;
}
}