MDL-66335 behat: generic step for navigating direct to specific pages

This commit is contained in:
Tim Hunt
2019-10-14 13:13:32 +01:00
parent badb6a92c4
commit 10bf14282c
2 changed files with 180 additions and 0 deletions
+50
View File
@@ -1002,6 +1002,56 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
}
}
/**
* Convert page names to URLs for steps like 'When I am on the "[page name]" page'.
*
* You should override this as appropriate for your plugin. The method
* {@link behat_navigation::resolve_core_page_url()} is a good example.
*
* Your overridden method should document the recognised page types with
* a table like this:
*
* Recognised page names are:
* | Page | Description |
*
* @param string $page name of the page, with the component name removed e.g. 'Admin notification'.
* @return moodle_url the corresponding URL.
* @throws Exception with a meaningful error message if the specified page cannot be found.
*/
protected function resolve_page_url(string $page): moodle_url {
throw new Exception('Component "' . get_class($this) .
'" does not support the generic \'When I am on the "' . $page .
'" page\' navigation step.');
}
/**
* Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'.
*
* A typical example might be:
* When I am on the "Test quiz" "mod_quiz > Responses report" page
* which would cause this method in behat_mod_quiz to be called with
* arguments 'Responses report', 'Test quiz'.
*
* You should override this as appropriate for your plugin. The method
* {@link behat_navigation::resolve_core_page_instance_url()} is a good example.
*
* Your overridden method should document the recognised page types with
* a table like this:
*
* Recognised page names are:
* | Type | identifier meaning | Description |
*
* @param string $type identifies which type of page this is, e.g. 'Attempt review'.
* @param string $identifier identifies the particular page, e.g. 'Test quiz > student > Attempt 1'.
* @return moodle_url the corresponding URL.
* @throws Exception with a meaningful error message if the specified page cannot be found.
*/
protected function resolve_page_instance_url(string $type, string $identifier): moodle_url {
throw new Exception('Component "' . get_class($this) .
'" does not support the generic \'When I am on the "' . $identifier .
'" "' . $type . '" page\' navigation step.');
}
/**
* Gets the required timeout in seconds.
*
+130
View File
@@ -550,6 +550,136 @@ class behat_navigation extends behat_base {
$USER = $globuser;
}
/**
* Open a given page, belonging to a plugin or core component.
*
* The page-type are interpreted by each plugin to work out the
* corresponding URL. See the resolve_url method in each class like
* behat_mod_forum. That method should document which page types are
* recognised, and how the name identifies them.
*
* For pages belonging to core, the 'core > ' bit is omitted.
*
* @When I am on the :page page
* @param string $page the component and page name.
* E.g. 'Admin notifications' or 'core_user > Preferences'.
* @throws Exception if the specified page cannot be determined.
*/
public function i_am_on_page(string $page) {
list($component, $name) = $this->parse_page_name($page);
if ($component === 'core') {
$url = $this->resolve_core_page_url($name);
} else {
$context = behat_context_helper::get('behat_' . $component);
$url = $context->resolve_page_url($name);
}
$this->getSession()->visit($this->locate_path($url->out_as_local_url()));
}
/**
* Parse a full page name like 'Admin notifications' or 'core_user > Preferences'.
*
* E.g. parsing 'mod_quiz > View' gives ['mod_quiz', 'View'].
*
* @param string $page the full page name
* @return array with two elements, component and page name.
*/
protected function parse_page_name(string $page): array {
$dividercount = substr_count($page, ' > ');
if ($dividercount === 0) {
return ['core', $page];
} else if ($dividercount === 1) {
list($component, $name) = explode(' > ', $page);
if ($component === 'core') {
throw new coding_exception('Do not specify the component "core > ..." for core pages.');
}
return [$component, $name];
} else {
throw new coding_exception('The page name most be in the form ' .
'"{page-name}" for core pages, or "{component} > {page-name}" ' .
'for pages belonging to other components. ' .
'For example "Admin notifications" or "mod_quiz > View".');
}
}
/**
* Open a given instance of a page, belonging to a plugin or core component.
*
* The instance identifier and page-type are interpreted by each plugin to
* work out the corresponding URL. See the resolve_page_instance_url method
* in each class like behat_mod_forum. That method should document which page
* types are recognised, and how the name identifies them.
*
* For pages belonging to core, the 'core > ' bit is omitted.
*
* @When I am on the :identifier :type page
* @param string $identifier identifies the particular page. E.g. 'Test quiz'.
* @param string $type the component and page type. E.g. 'mod_quiz > View'.
* @throws Exception if the specified page cannot be determined.
*/
public function i_am_on_page_instance(string $identifier, string $type) {
list($component, $type) = $this->parse_page_name($type);
if ($component === 'core') {
$url = $this->resolve_core_page_instance_url($type, $identifier);
} else {
$context = behat_context_helper::get('behat_' . $component);
$url = $context->resolve_page_instance_url($type, $identifier);
}
$this->getSession()->visit($this->locate_path($url->out_as_local_url()));
}
/**
* Convert core page names to URLs for steps like 'When I am on the "[page name]" page'.
*
* Recognised page names are:
* | Homepage | Homepage (normally dashboard). |
* | Admin notifications | Admin notification screen. |
*
* @param string $name identifies which identifies this page, e.g. 'Homepage', 'Admin notifications'.
* @return moodle_url the corresponding URL.
* @throws Exception with a meaningful error message if the specified page cannot be found.
*/
protected function resolve_core_page_url(string $name): moodle_url {
switch ($name) {
case 'Homepage':
return new moodle_url('/');
case 'Admin notifications':
return new moodle_url('/admin/');
default:
throw new Exception('Unrecognised core page type "' . $name . '."');
}
}
/**
* Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'.
*
* Recognised page names are:
* | Page type | Identifier meaning | description |
* | Category page | category idnumber | List of courses in that category. |
*
* @param string $type identifies which type of page this is, e.g. 'Category page'.
* @param string $identifier identifies the particular page, e.g. 'test-cat'.
* @return moodle_url the corresponding URL.
* @throws Exception with a meaningful error message if the specified page cannot be found.
*/
protected function resolve_core_page_instance_url(string $type, string $identifier): moodle_url {
global $DB;
switch ($type) {
case 'Category page':
$categoryid = $DB->get_field('course_categories', 'id', ['idnumber' => $identifier]);
if (!$categoryid) {
throw new Exception('The specified category with idnumber "' . $identifier . '" does not exist');
}
return new moodle_url('/course/category.php', ['id' => $categoryid]);
default:
throw new Exception('Unrecognised core page type "' . $type . '."');
}
}
/**
* Opens the course homepage.
*