diff --git a/admin/tool/behat/cli/util.php b/admin/tool/behat/cli/util.php
index 93c5914d8b1..a83b6639836 100644
--- a/admin/tool/behat/cli/util.php
+++ b/admin/tool/behat/cli/util.php
@@ -32,9 +32,7 @@ require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/behat/locallib.php');
list($options, $unrecognized) = cli_get_params(
array(
'help' => false,
- 'stepsdefinitions' => false,
'runtests' => false,
- 'filter' => false,
'tags' => false,
'extra' => false,
'with-javascript' => false,
@@ -51,7 +49,6 @@ Behat tool
Ensure the user who executes the action has permissions over behat installation
Options:
---stepsdefinitions Displays the available steps definitions (accepts --filter=\"\" option to restrict the list to the matching definitions)
--runtests Runs the tests (accepts --with-javascript option, --tags=\"\" option to execute only the matching tests and --extra=\"\" to specify extra behat options)
--testenvironment Allows the test environment to be accesses through the built-in server (accepts value 'enable' or 'disable')
@@ -73,7 +70,7 @@ if ($unrecognized) {
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
-$commands = array('stepsdefinitions', 'runtests', 'testenvironment');
+$commands = array('runtests', 'testenvironment');
foreach ($commands as $command) {
if ($options[$command]) {
$action = $command;
@@ -88,10 +85,6 @@ if (empty($action)) {
switch ($action) {
- case 'stepsdefinitions':
- tool_behat::stepsdefinitions($options['filter']);
- break;
-
case 'runtests':
tool_behat::runtests($options['with-javascript'], $options['tags'], $options['extra']);
break;
diff --git a/admin/tool/behat/index.php b/admin/tool/behat/index.php
index f1c7b5f1b9e..31653c42a19 100644
--- a/admin/tool/behat/index.php
+++ b/admin/tool/behat/index.php
@@ -26,8 +26,29 @@ require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/behat/locallib.php');
-$action = optional_param('action', 'info', PARAM_ALPHAEXT);
+$filter = optional_param('filter', '', PARAM_ALPHANUMEXT);
+$type = optional_param('type', false, PARAM_ALPHAEXT);
+$component = optional_param('component', '', PARAM_ALPHAEXT);
admin_externalpage_setup('toolbehat');
-call_user_func('tool_behat::' . $action);
+// Getting available steps definitions from behat.
+$steps = tool_behat::stepsdefinitions($type, $component, $filter);
+
+// Form.
+$componentswithsteps = array(
+ '' => get_string('allavailablesteps', 'tool_behat'),
+ 'nomoodle' => get_string('nomoodlesteps', 'tool_behat'),
+);
+$components = tool_behat::get_components_steps_definitions();
+if ($components) {
+ foreach ($components as $component => $filepath) {
+ $componentswithsteps[$component] = 'Moodle ' . substr($component, 6);
+ }
+}
+$form = new steps_definitions_form(null, array('components' => $componentswithsteps));
+
+// Output contents.
+$renderer = $PAGE->get_renderer('tool_behat');
+echo $renderer->render_stepsdefinitions($steps, $form);
+
diff --git a/admin/tool/behat/lang/en/tool_behat.php b/admin/tool/behat/lang/en/tool_behat.php
index 33a5a051f13..1f43264fe05 100644
--- a/admin/tool/behat/lang/en/tool_behat.php
+++ b/admin/tool/behat/lang/en/tool_behat.php
@@ -23,15 +23,26 @@
*/
$string['actionnotsupported'] = 'Action not supported';
+$string['allavailablesteps'] = 'All the available steps';
$string['commandinfo'] = 'Info';
$string['commandruntests'] = 'Run tests';
$string['commandstepsdefinitions'] = 'Steps definitions list';
$string['commandswitchenvironment'] = 'Switch environment';
$string['finished'] = 'Process finished';
-$string['nobehatpath'] = 'You must specify the path to moodle-acceptance-tests.';
+$string['giveninfo'] = 'Given. Processes to set up the environment';
+$string['installinfo'] = 'for installation and tests execution info';
+$string['moreinfoin'] = 'More info in';
+$string['newstepsinfo'] = 'for info about adding new steps definitions';
+$string['newtestsinfo'] = 'for info about writting new tests';
+$string['nobehatpath'] = 'Behat path not found, use \'behatpath\' setting to specify it';
+$string['nomoodlesteps'] = 'Generic web application steps';
$string['nostepsdefinitions'] = 'There aren\'t steps definitions matching this filter';
$string['pluginname'] = 'Acceptance testing';
-$string['stepsdefinitions'] = 'Steps definitions which contains';
-$string['stepsdefinitionsemptyfilter'] = 'all steps definitions if empty';
-$string['viewsteps'] = 'View available steps definitions';
-$string['wrongbehatsetup'] = 'Something is wrong with the setup, check moodle-acceptance-tests runs well on CLI and check your \'behatpath\' setting value is pointing to the right directory';
\ No newline at end of file
+$string['stepsdefinitionscomponent'] = 'Area';
+$string['stepsdefinitionscontains'] = 'Contains';
+$string['stepsdefinitionsfilters'] = 'Steps definitions';
+$string['stepsdefinitionstype'] = 'Type';
+$string['theninfo'] = 'Then. Checkings to ensure the outcomes are the expected ones';
+$string['viewsteps'] = 'Filter';
+$string['wheninfo'] = 'When. Actions that provokes an event';
+$string['wrongbehatsetup'] = 'Something is wrong with the setup, check moodle-acceptance-tests runs well on CLI and check your \'behatpath\' setting value is pointing to the right directory';
diff --git a/admin/tool/behat/locallib.php b/admin/tool/behat/locallib.php
index 2b5cc767b1a..237f26233e0 100644
--- a/admin/tool/behat/locallib.php
+++ b/admin/tool/behat/locallib.php
@@ -26,6 +26,8 @@ require_once($CFG->libdir . '/filestorage/file_exceptions.php');
require_once($CFG->libdir . '/phpunit/bootstraplib.php');
require_once($CFG->libdir . '/phpunit/classes/tests_finder.php');
+require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/behat/steps_definitions_form.php');
+
/**
* Behat commands manager
*
@@ -35,84 +37,60 @@ require_once($CFG->libdir . '/phpunit/classes/tests_finder.php');
*/
class tool_behat {
+ /**
+ * Path where each component's tests are stored
+ * @var string
+ */
private static $behat_tests_path = '/tests/behat';
/**
- * Displays basic info about acceptance tests
+ * Steps types
+ * @var array
*/
- public static function info() {
+ private static $steps_types = array('given', 'when', 'then');
- $html = self::get_header();
- $html .= self::get_info();
- $html .= self::get_steps_definitions_form();
- $html .= self::get_footer();
-
- echo $html;
- }
+ public static $docsurl = 'http://docs.moodle.org/dev/Acceptance_testing';
/**
* Lists the available steps definitions
- * @param string $filter Keyword to filter the list of steps definitions availables
+ *
+ * @param string $type
+ * @param string $component
+ * @param string $filter
+ * @return string
*/
- public static function stepsdefinitions($filter = false) {
+ public static function stepsdefinitions($type, $component, $filter) {
global $CFG;
self::check_behat_setup();
- self::update_config_file();
+ // The loaded steps depends on the component specified.
+ self::update_config_file($component);
- // Priority to the one specified as argument.
- if (!$filter) {
- $filter = optional_param('filter', false, PARAM_ALPHANUMEXT);
+ if ($type) {
+ $filter .= '&&' . $type;
}
if ($filter) {
- $filteroption = ' -d ' . $filter;
+ $filteroption = ' -d "' . $filter . '"';
} else {
$filteroption = ' -di';
}
- $color = '';
- if (CLI_SCRIPT) {
- $color = '--ansi ';
- }
-
$currentcwd = getcwd();
chdir($CFG->behatpath);
- exec('bin/behat ' . $color . ' --config="' . self::get_behat_config_filepath() . '" ' . $filteroption, $steps, $code);
+ exec('bin/behat --config="' . self::get_behat_config_filepath() . '" ' . $filteroption, $steps, $code);
chdir($currentcwd);
- // Outputing steps.
-
- $content = '';
if ($steps) {
- foreach ($steps as $line) {
-
- // Skipping the step definition context.
- if (strpos($line, '#') == 0) {
- if (CLI_SCRIPT) {
- $content .= $line . PHP_EOL;
- } else {
- $content .= htmlentities($line) . '
';
- }
-
- }
- }
+ $stepshtml = implode('', $steps);
}
- if ($content === '') {
- $content = get_string('nostepsdefinitions', 'tool_behat');
+ if (!isset($stepshtml) || $stepshtml == '') {
+ $stepshtml = get_string('nostepsdefinitions', 'tool_behat');
}
- if (!CLI_SCRIPT) {
- $html = self::get_header();
- $html .= self::get_steps_definitions_form($filter);
- $html .= html_writer::tag('div', $content, array('id' => 'steps-definitions'));
- $html .= self::get_footer();
- echo $html;
- } else {
- echo $content;
- }
+ return $stepshtml;
}
/**
@@ -149,7 +127,7 @@ class tool_behat {
public static function runtests($withjavascript = false, $tags = false, $extra = false) {
global $CFG;
- // Checks that the behat reference is properly set up
+ // Checks that the behat reference is properly set up.
self::check_behat_setup();
// Check that PHPUnit test environment is correctly set up.
@@ -159,7 +137,7 @@ class tool_behat {
@set_time_limit(0);
- // No javascript by default
+ // No javascript by default.
if (!$withjavascript && strstr($tags, 'javascript') == false) {
$jsstr = '~javascript';
}
@@ -181,7 +159,7 @@ class tool_behat {
$extra = '';
}
- // Starts built-in server and inits test mode
+ // Starts built-in server and inits test mode.
self::start_test_mode();
$server = self::start_test_server();
@@ -194,30 +172,38 @@ class tool_behat {
ob_end_clean();
chdir($currentcwd);
- // Stops built-in server and stops test mode
+ // Stops built-in server and stops test mode.
self::stop_test_server($server[0], $server[1]);
self::stop_test_mode();
// Output.
- echo self::get_header();
echo $output;
- echo self::get_footer();
}
/**
* Updates the config file
+ * @param string $component Restricts the obtained steps definitions to the specified component
* @throws file_exception
*/
- private static function update_config_file() {
+ private static function update_config_file($component = '') {
global $CFG;
$behatpath = rtrim($CFG->behatpath, '/');
+ // Not extra contexts when component is specified.
+ $loadbuiltincontexts = '0';
+ if ($component == '' || $component == 'nomoodle') {
+ $loadbuiltincontexts = '1';
+ }
+
// Basic behat dependencies.
$contents = 'default:
paths:
features: ' . $behatpath . '/features
bootstrap: ' . $behatpath . '/features/bootstrap
+ context:
+ parameters:
+ loadbuiltincontexts: ' . $loadbuiltincontexts . '
extensions:
Behat\MinkExtension\Extension:
base_url: ' . $CFG->test_wwwroot . '
@@ -245,19 +231,14 @@ class tool_behat {
$contents .= ' features:' . implode(PHP_EOL . ' - ', $featurespaths) . PHP_EOL;
}
- // Gets all the components with steps definitions.
- $components = tests_finder::get_components_with_tests('stepsdefinitions');
- if ($components) {
- $stepsdefinitions = array('');
- foreach ($components as $componentname => $componentpath) {
- $componentpath = self::clean_path($componentpath);
- $diriterator = new DirectoryIterator($componentpath . self::$behat_tests_path);
- $regite = new RegexIterator($diriterator, '|behat_.*\.php$|');
- // All behat_*.php inside self::$behat_tests_path are added as steps definitions files
- foreach ($regite as $file) {
- $key = $file->getBasename('.php');
- $stepsdefinitions[$key] = $key . ': ' . $file->getPathname();
+ // Gets all the components with steps definitions.
+ $steps = self::get_components_steps_definitions();
+ if ($steps && $component != 'nomoodle') {
+ $stepsdefinitions = array('');
+ foreach ($steps as $key => $filepath) {
+ if ($component == '' || $component === $key) {
+ $stepsdefinitions[$key] = $key . ': ' . $filepath;
}
}
$contents .= ' steps_definitions:' . implode(PHP_EOL . ' ', $stepsdefinitions) . PHP_EOL;
@@ -271,6 +252,40 @@ class tool_behat {
}
+ /**
+ * Gets the list of Moodle steps definitions
+ *
+ * Class name as a key and the filepath as value
+ *
+ * Externalized from update_config_file() to use
+ * it from the steps definitions web interface
+ *
+ * @return array
+ */
+ public static function get_components_steps_definitions() {
+
+ $components = tests_finder::get_components_with_tests('stepsdefinitions');
+ if (!$components) {
+ return false;
+ }
+
+ $stepsdefinitions = array();
+ foreach ($components as $componentname => $componentpath) {
+ $componentpath = self::clean_path($componentpath);
+ $diriterator = new DirectoryIterator($componentpath . self::$behat_tests_path);
+ $regite = new RegexIterator($diriterator, '|behat_.*\.php$|');
+
+ // All behat_*.php inside self::$behat_tests_path are added as steps definitions files.
+ foreach ($regite as $file) {
+ $key = $file->getBasename('.php');
+ $stepsdefinitions[$key] = $file->getPathname();
+ }
+ }
+
+ return $stepsdefinitions;
+ }
+
+
/**
* Cleans the path returned by get_components_with_tests() to standarize it
*
@@ -323,11 +338,15 @@ class tool_behat {
// Moodle setting.
if (empty($CFG->behatpath)) {
$msg = get_string('nobehatpath', 'tool_behat');
- $url = $CFG->wwwroot . '/' . $CFG->admin . '/settings.php?section=systempaths';
+ // With HTML.
+ $docslink = tool_behat::$docsurl;
if (!CLI_SCRIPT) {
- $msg .= ' ' . html_writer::tag('a', get_string('systempaths', 'admin'), array('href' => $url));
+ $docslink = html_writer::tag('a', $docslink, array('href' => $docslink, 'target' => '_blank'));
+ $systempathsurl = $CFG->wwwroot . '/' . $CFG->admin . '/settings.php?section=systempaths';
+ $msg .= ' (' . html_writer::tag('a', get_string('systempaths', 'admin'), array('href' => $systempathsurl)) . ')';
}
+ $msg .= '. ' . get_string('moreinfoin', 'tool_behat') . ' ' . $docslink;
notice($msg);
}
@@ -362,7 +381,8 @@ class tool_behat {
$behatdir = self::get_behat_dir();
- $contents = '$CFG->phpunit_prefix and $CFG->phpunit_dataroot are currently used as $CFG->prefix and $CFG->dataroot';
+ $contents = '$CFG->test_wwwroot, $CFG->phpunit_prefix and $CFG->phpunit_dataroot' .
+ ' are currently used as $CFG->wwwroot, $CFG->prefix and $CFG->dataroot';
$filepath = $behatdir . '/test_environment_enabled.txt';
if (!file_put_contents($filepath, $contents)) {
throw new file_exception('cannotcreatefile', $filepath);
@@ -386,6 +406,8 @@ class tool_behat {
$server = str_replace('http://', '', $CFG->test_wwwroot);
$process = proc_open('php -S ' . $server, $descriptorspec, $pipes, $CFG->dirroot);
+ // TODO If it's already started close pipes.
+
if (!is_resource($process)) {
print_error('testservercantrun');
}
@@ -510,109 +532,4 @@ class tool_behat {
return self::get_behat_dir() . '/behat.yml';
}
- /**
- * Returns header output
- * @return string
- */
- private static function get_header() {
- global $OUTPUT;
-
- $action = optional_param('action', 'info', PARAM_ALPHAEXT);
-
- if (CLI_SCRIPT) {
- return '';
- }
-
- $title = get_string('pluginname', 'tool_behat') . ' - ' . get_string('command' . $action, 'tool_behat');
- $html = $OUTPUT->header();
- $html .= $OUTPUT->heading($title);
-
- return $html;
- }
-
- /**
- * Returns footer output
- * @return string
- */
- private static function get_footer() {
- global $OUTPUT;
-
- if (CLI_SCRIPT) {
- return '';
- }
-
- return $OUTPUT->footer();
- }
-
- /**
- * Returns a message and a button to continue if web execution
- * @param string $html
- * @param string $url
- * @return string
- */
- private static function output_success($html, $url = false) {
- global $CFG, $OUTPUT;
-
- if (!$url) {
- $url = $CFG->wwwroot . '/' . $CFG->admin . '/tool/behat/index.php';
- }
-
- if (!CLI_SCRIPT) {
- $html = $OUTPUT->box($html, 'generalbox', 'notice');
- $html .= $OUTPUT->continue_button($url);
- }
-
- return $html;
- }
-
- /**
- * Returns the installation instructions
- *
- * (hardcoded in English)
- *
- * @return string
- */
- private static function get_info() {
- global $OUTPUT;
-
- $url = 'http://docs.moodle.org/dev/Acceptance_testing';
-
- $html = $OUTPUT->box_start();
- $html .= html_writer::tag('h1', 'Info');
- $html .= html_writer::tag('div', 'Follow ' . $url . ' instructions for info about installation and tests execution');
- $html .= $OUTPUT->box_end();
-
- return $html;
- }
-
- /**
- * Returns the steps definitions form
- * @param string $filter To filter the steps definitions list by keyword
- * @return string
- */
- private static function get_steps_definitions_form($filter = false) {
- global $OUTPUT;
-
- if ($filter === false) {
- $filter = '';
- } else {
- $filter = s($filter);
- }
-
- $html = $OUTPUT->box_start();
- $html .= '