MDL-72179 behat: Improve core page resolvers

This commit makes the following improvements to core page resolverss:
* allows for mixed case naming (course, Course, etc.)
* allows fields other than the idnumber to be specified:
** course: idnumber, shortname, fullname
** course category: idnumber, name

Whilst some of these fields are not unique, they will typically be
unique in most test scenarios. Where they are not then the idnumber
should be used in preference.
This commit is contained in:
Andrew Nicols 2021-07-19 14:06:37 +08:00
parent 8c0853d026
commit 730d6cb94e
4 changed files with 163 additions and 47 deletions

View File

@ -0,0 +1,64 @@
@tool @tool_behat
Feature: Use core page resolvers for the I am on the page steps
In order to write tests correctly
As a developer
I need to have steps which take me straight to a page
Scenario Outline: When I am on an instance
Given the following "course" exists:
| fullname | Economics 101 |
| shortname | ECON101 |
| idnumber | 2021-econ101 |
And the following "activity" exists:
| course | ECON101 |
| activity | forum |
| name | Fundamentals of Economics |
| idnumber | fundamentalsofeconomics |
And I log in as "admin"
When I am on the <identifier> <type> page
Then I should see "<shouldsee>"
Examples:
| Course Full name | "Economics 101" | course | Fundamentals of Economics |
| Course Short name | ECON101 | COURSE | Fundamentals of Economics |
| Course idnumber | "2021-econ101" | Course | Fundamentals of Economics |
| Forum idnumber | fundamentalsofeconomics | Activity | Add a new discussion |
Scenario Outline: When I am on an instance logged in as
Given the following "course" exists:
| fullname | Economics 101 |
| shortname | ECON101 |
| idnumber | 2021-econ101 |
And the following "activity" exists:
| course | ECON101 |
| activity | forum |
| name | Fundamentals of Economics |
| idnumber | fundamentalsofeconomics |
When I am on the <identifier> <type> page logged in as admin
Then I should see "<shouldsee>"
Examples:
| description | identifier | type | shouldsee |
| Course Full name | "Economics 101" | course | Fundamentals of Economics |
| Course Short name | ECON101 | COURSE | Fundamentals of Economics |
| Course idnumber | "2021-econ101" | Course | Fundamentals of Economics |
| Forum idnumber | fundamentalsofeconomics | Activity | Add a new discussion |
Scenario Outline: When I am on a named page
Given I log in as "admin"
When I am on the <identifier> page
Then I should see "<shouldsee>"
Examples:
| description | identifier | shouldsee |
| Admin page | Admin | Check for available updates |
| Home page | Homepage | Recently accessed courses |
@javascript
Scenario Outline: When I am on a named page logged in as
When I am on the <identifier> page logged in as admin
Then I should see "<shouldsee>"
Examples:
| description | identifier | shouldsee |
| Home page | Homepage | Recently accessed courses |

View File

@ -1330,44 +1330,6 @@ class behat_course extends behat_base {
return $this->getSession()->getPage()->findButton(get_string('turneditingoff')) ? true : false;
}
/**
* Returns the id of the category with the given idnumber.
*
* Please note that this function requires the category to exist. If it does not exist an ExpectationException is thrown.
*
* @param string $idnumber
* @return string
* @throws ExpectationException
*/
protected function get_category_id($idnumber) {
global $DB;
try {
return $DB->get_field('course_categories', 'id', array('idnumber' => $idnumber), MUST_EXIST);
} catch (dml_missing_record_exception $ex) {
throw new ExpectationException(sprintf("There is no category in the database with the idnumber '%s'", $idnumber),
$this->getSession());
}
}
/**
* Returns the id of the course with the given idnumber.
*
* Please note that this function requires the category to exist. If it does not exist an ExpectationException is thrown.
*
* @param string $idnumber
* @return string
* @throws ExpectationException
*/
protected function get_course_id($idnumber) {
global $DB;
try {
return $DB->get_field('course', 'id', array('idnumber' => $idnumber), MUST_EXIST);
} catch (dml_missing_record_exception $ex) {
throw new ExpectationException(sprintf("There is no course in the database with the idnumber '%s'", $idnumber),
$this->getSession());
}
}
/**
* Returns the category node from within the listing on the management page.
*

View File

@ -1443,4 +1443,95 @@ EOF;
$timeout = self::get_real_timeout(30) * 1000 * $factor;
$driver->getWebDriver()->getCommandExecutor()->setRequestTimeout($timeout);
}
/**
* Get the course category id from an identifier.
*
* The category idnumber, and name are checked.
*
* @param string $identifier
* @return int|null
*/
protected function get_category_id(string $identifier): ?int {
global $DB;
$sql = <<<EOF
SELECT id
FROM {course_categories}
WHERE idnumber = :idnumber
OR name = :name
EOF;
$result = $DB->get_field_sql($sql, [
'idnumber' => $identifier,
'name' => $identifier,
]);
return $result ?: null;
}
/**
* Get the course id from an identifier.
*
* The course idnumber, shortname, and fullname are checked.
*
* @param string $identifier
* @return int|null
*/
protected function get_course_id(string $identifier): ?int {
global $DB;
$sql = <<<EOF
SELECT id
FROM {course}
WHERE idnumber = :idnumber
OR shortname = :shortname
OR fullname = :fullname
EOF;
$result = $DB->get_field_sql($sql, [
'idnumber' => $identifier,
'shortname' => $identifier,
'fullname' => $identifier,
]);
return $result ?: null;
}
/**
* Get the activity course module id from its idnumber.
*
* Note: Only idnumber is supported here, not name at this time.
*
* @param string $identifier
* @return cm_info|null
*/
protected function get_course_module_for_identifier(string $identifier): ?cm_info {
global $DB;
$coursetable = new \core\dml\table('course', 'c', 'c');
$courseselect = $coursetable->get_field_select();
$coursefrom = $coursetable->get_from_sql();
$cmtable = new \core\dml\table('course_modules', 'cm', 'cm');
$cmfrom = $cmtable->get_from_sql();
$sql = <<<EOF
SELECT {$courseselect}, cm.id as cmid
FROM {$cmfrom}
INNER JOIN {$coursefrom} ON c.id = cm.course
WHERE cm.idnumber = :idnumber
EOF;
$result = $DB->get_record_sql($sql, [
'idnumber' => $identifier,
]);
if ($result) {
$course = $coursetable->extract_from_result($result);
return get_fast_modinfo($course)->get_cm($result->cmid);
}
return null;
}
}

View File

@ -710,29 +710,28 @@ class behat_navigation extends behat_base {
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]);
switch (strtolower($type)) {
case 'category page':
$categoryid = $this->get_category_id($identifier);
if (!$categoryid) {
throw new Exception('The specified category with idnumber "' . $identifier . '" does not exist');
}
return new moodle_url('/course/category.php', ['id' => $categoryid]);
case 'Course':
$courseid = $DB->get_field_select('course', 'id', 'shortname = ?', [$identifier], IGNORE_MISSING);
case 'course':
$courseid = $this->get_course_id($identifier);
if (!$courseid) {
throw new Exception('The specified course with shortname, fullname, or idnumber "' .
$identifier . '" does not exist');
}
return new moodle_url('/course/view.php', ['id' => $courseid]);
case 'Activity':
$cm = $DB->get_record('course_modules', ['idnumber' => $identifier], 'id, course', IGNORE_MISSING);
case 'activity':
$cm = $this->get_course_module_for_identifier($identifier);
if (!$cm) {
throw new Exception('The specified activity with idnumber "' . $identifier . '" does not exist');
}
$modinfo = get_fast_modinfo($cm->course);
return $modinfo->cms[$cm->id]->url;
return $cm->url;
default:
throw new Exception('Unrecognised core page type "' . $type . '."');