Skip to content

Commit

Permalink
MDL-72179 behat: Improve core page resolvers
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
andrewnicols committed Jul 23, 2021
1 parent 8c0853d commit 730d6cb
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 47 deletions.
64 changes: 64 additions & 0 deletions admin/tool/behat/tests/behat/i_am_on_page.feature
Original file line number Diff line number Diff line change
@@ -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 |
38 changes: 0 additions & 38 deletions course/tests/behat/behat_course.php
Original file line number Diff line number Diff line change
Expand Up @@ -1330,44 +1330,6 @@ protected function is_editing_on() {
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.
*
Expand Down
91 changes: 91 additions & 0 deletions lib/behat/classes/behat_session_trait.php
Original file line number Diff line number Diff line change
Expand Up @@ -1443,4 +1443,95 @@ public function set_test_timeout_factor(int $factor = 1): void {
$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;
}
}
17 changes: 8 additions & 9 deletions lib/tests/behat/behat_navigation.php
Original file line number Diff line number Diff line change
Expand Up @@ -710,29 +710,28 @@ protected function resolve_core_page_url(string $name): moodle_url {
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 . '."');
Expand Down

0 comments on commit 730d6cb

Please sign in to comment.