Merge branch 'MDL-66675-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE
This commit is contained in:
@@ -812,6 +812,10 @@ $CFG->admin = 'admin';
|
||||
// Example:
|
||||
// $CFG->behat_faildump_path = '/my/path/to/save/failure/dumps';
|
||||
//
|
||||
// You can make behat pause upon failure to help you diagnose and debug problems with your tests.
|
||||
//
|
||||
// $CFG->behat_pause_on_fail = true;
|
||||
//
|
||||
// You can specify db, selenium wd_host etc. for behat parallel run by setting following variable.
|
||||
// Example:
|
||||
// $CFG->behat_parallel_run = array (
|
||||
|
||||
@@ -31,6 +31,9 @@ require_once(__DIR__ . '/behat_command.php');
|
||||
require_once(__DIR__ . '/behat_config_manager.php');
|
||||
|
||||
require_once(__DIR__ . '/../../filelib.php');
|
||||
require_once(__DIR__ . '/../../clilib.php');
|
||||
|
||||
use Behat\Mink\Session;
|
||||
|
||||
/**
|
||||
* Init/reset utilities for Behat database and dataroot
|
||||
@@ -373,4 +376,38 @@ class behat_util extends testing_util {
|
||||
// $CFG values from the old run. @see set_config.
|
||||
initialise_cfg();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause execution immediately.
|
||||
*
|
||||
* @param Session $session
|
||||
* @param string $message The message to show when pausing.
|
||||
* This will be passed through cli_ansi_format so appropriate ANSI formatting and features are available.
|
||||
*/
|
||||
public static function pause(Session $session, string $message): void {
|
||||
$posixexists = function_exists('posix_isatty');
|
||||
|
||||
// Make sure this step is only used with interactive terminal (if detected).
|
||||
if ($posixexists && !@posix_isatty(STDOUT)) {
|
||||
throw new ExpectationException('Break point should only be used with interactive terminal.', $session);
|
||||
}
|
||||
|
||||
// Save the cursor position, ring the bell, and add a new line.
|
||||
fwrite(STDOUT, cli_ansi_format("<cursor:save><bell><newline>"));
|
||||
|
||||
// Output the formatted message and reset colour back to normal.
|
||||
$formattedmessage = cli_ansi_format("{$message}<colour:normal>");
|
||||
fwrite(STDOUT, $formattedmessage);
|
||||
|
||||
// Wait for input.
|
||||
fread(STDIN, 1024);
|
||||
|
||||
// Move the cursor back up to the previous position, then restore the original position stored earlier, and move
|
||||
// it back down again.
|
||||
fwrite(STDOUT, cli_ansi_format("<cursor:up><cursor:up><cursor:restore><cursor:down><cursor:down>"));
|
||||
|
||||
// Add any extra lines back if the provided message was spread over multiple lines.
|
||||
$linecount = count(explode("\n", $formattedmessage));
|
||||
fwrite(STDOUT, str_repeat(cli_ansi_format("<cursor:down>"), $linecount - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,3 +227,59 @@ function cli_logo($padding=2, $return=false) {
|
||||
cli_write($logo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitute cursor, colour, and bell placeholders in a CLI output to ANSI escape characters when ANSI is available.
|
||||
*
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
function cli_ansi_format(string $message): string {
|
||||
global $CFG;
|
||||
|
||||
$replacements = [
|
||||
"<newline>" => "\n",
|
||||
"<bell>" => "\007",
|
||||
|
||||
// Cursor movement: https://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html.
|
||||
"<cursor:save>" => "\033[s",
|
||||
"<cursor:restore>" => "\033[u",
|
||||
"<cursor:up>" => "\033[1A",
|
||||
"<cursor:down>" => "\033[1B",
|
||||
"<cursor:forward>" => "\033[1C",
|
||||
"<cursor:back>" => "\033[1D",
|
||||
];
|
||||
|
||||
$colours = [
|
||||
'normal' => '0;0',
|
||||
'black' => '0;30',
|
||||
'darkGray' => '1;30',
|
||||
'blue' => '0;34',
|
||||
'lightBlue' => '1;34',
|
||||
'green' => '0;32',
|
||||
'lightGreen' => '1;32',
|
||||
'cyan' => '0;36',
|
||||
'lightCyan' => '1;36',
|
||||
'red' => '0;31',
|
||||
'lightRed' => '1;31',
|
||||
'purple' => '0;35',
|
||||
'lightPurple' => '1;35',
|
||||
'brown' => '0;33',
|
||||
'yellow' => '1;33',
|
||||
'lightYellow' => '0;93',
|
||||
'lightGray' => '0;37',
|
||||
'white' => '1;37',
|
||||
];
|
||||
|
||||
foreach ($colours as $colour => $code) {
|
||||
$replacements["<colour:{$colour}>"] = "\033[{$code}m";
|
||||
}
|
||||
|
||||
// Windows don't support ANSI code by default, but does if ANSICON is available.
|
||||
$isansicon = getenv('ANSICON');
|
||||
if (($CFG->ostype === 'WINDOWS') && empty($isansicon)) {
|
||||
return str_replace(array_keys($replacements), '', $message);
|
||||
}
|
||||
|
||||
return str_replace(array_keys($replacements), array_values($replacements), $message);
|
||||
}
|
||||
|
||||
@@ -1595,27 +1595,9 @@ EOF;
|
||||
*
|
||||
* @Then /^(?:|I )pause(?:| scenario execution)$/
|
||||
*/
|
||||
public function i_pause_scenario_executon() {
|
||||
global $CFG;
|
||||
|
||||
$posixexists = function_exists('posix_isatty');
|
||||
|
||||
// Make sure this step is only used with interactive terminal (if detected).
|
||||
if ($posixexists && !@posix_isatty(STDOUT)) {
|
||||
$session = $this->getSession();
|
||||
throw new ExpectationException('Break point should only be used with interative terminal.', $session);
|
||||
}
|
||||
|
||||
// Windows don't support ANSI code by default, but with ANSICON.
|
||||
$isansicon = getenv('ANSICON');
|
||||
if (($CFG->ostype === 'WINDOWS') && empty($isansicon)) {
|
||||
fwrite(STDOUT, "Paused. Press Enter/Return to continue.");
|
||||
fread(STDIN, 1024);
|
||||
} else {
|
||||
fwrite(STDOUT, "\033[s\n\033[0;93mPaused. Press \033[1;31mEnter/Return\033[0;93m to continue.\033[0m");
|
||||
fread(STDIN, 1024);
|
||||
fwrite(STDOUT, "\033[2A\033[u\033[2B");
|
||||
}
|
||||
public function i_pause_scenario_execution() {
|
||||
$message = "<colour:lightYellow>Paused. Press <colour:lightRed>Enter/Return<colour:lightYellow> to continue.";
|
||||
behat_util::pause($this->getSession(), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -466,11 +466,7 @@ class behat_hooks extends behat_base {
|
||||
throw new coding_exception("Step '" . $scope->getStep()->getText() . "'' is undefined.");
|
||||
}
|
||||
|
||||
// Save the page content if the step failed.
|
||||
if (!empty($CFG->behat_faildump_path) &&
|
||||
$scope->getTestResult()->getResultCode() === Behat\Testwork\Tester\Result\TestResult::FAILED) {
|
||||
$this->take_contentdump($scope);
|
||||
}
|
||||
$isfailed = $scope->getTestResult()->getResultCode() === Behat\Testwork\Tester\Result\TestResult::FAILED;
|
||||
|
||||
// Abort any open transactions to prevent subsequent tests hanging.
|
||||
// This does the same as abort_all_db_transactions(), but doesn't call error_log() as we don't
|
||||
@@ -482,17 +478,30 @@ class behat_hooks extends behat_base {
|
||||
}
|
||||
}
|
||||
|
||||
if ($isfailed && !empty($CFG->behat_faildump_path)) {
|
||||
// Save the page content (html).
|
||||
$this->take_contentdump($scope);
|
||||
|
||||
if ($this->running_javascript()) {
|
||||
// Save a screenshot.
|
||||
$this->take_screenshot($scope);
|
||||
}
|
||||
}
|
||||
|
||||
if ($isfailed && !empty($CFG->behat_pause_on_fail)) {
|
||||
$exception = $scope->getTestResult()->getException();
|
||||
$message = "<colour:lightRed>Scenario failed. ";
|
||||
$message .= "<colour:lightYellow>Paused for inspection. Press <colour:lightRed>Enter/Return<colour:lightYellow> to continue.<newline>";
|
||||
$message .= "<colour:lightRed>Exception follows:<newline>";
|
||||
$message .= trim($exception->getMessage());
|
||||
behat_util::pause($this->getSession(), $message);
|
||||
}
|
||||
|
||||
// Only run if JS.
|
||||
if (!$this->running_javascript()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save a screenshot if the step failed.
|
||||
if (!empty($CFG->behat_faildump_path) &&
|
||||
$scope->getTestResult()->getResultCode() === Behat\Testwork\Tester\Result\TestResult::FAILED) {
|
||||
$this->take_screenshot($scope);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->wait_for_pending_js();
|
||||
self::$currentstepexception = null;
|
||||
|
||||
Reference in New Issue
Block a user