Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. 18 19 require_once (__DIR__ . '/behat_question_base.php'); 20 21 use Behat\Gherkin\Node\TableNode as TableNode; 22 use Behat\Mink\Exception\ExpectationException as ExpectationException; 23 use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; 24 25 /** 26 * Behat navigation hooks for core_question. 27 * 28 * @package core_question 29 * @category test 30 * @copyright 2022 The Open University 31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 */ 33 class behat_core_question extends behat_question_base { 34 35 /** 36 * Convert page names to URLs for steps like 'When I am on the "[page name]" page'. 37 * 38 * Recognised page names are: 39 * | None so far! | | 40 * 41 * @param string $page name of the page, with the component name removed e.g. 'Admin notification'. 42 * @return moodle_url the corresponding URL. 43 * @throws Exception with a meaningful error message if the specified page cannot be found. 44 */ 45 protected function resolve_page_url(string $page): moodle_url { 46 switch (strtolower($page)) { 47 default: 48 throw new Exception('Unrecognised core_question page type "' . $page . '."'); 49 } 50 } 51 52 /** 53 * Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'. 54 * 55 * Recognised page names are: 56 * | pagetype | name meaning | description | 57 * | course question bank | Course name | The question bank for a course | 58 * | course question import | Course name | The import questions screen for a course | 59 * | course question export | Course name | The export questions screen for a course | 60 * | preview | Question name | The screen to preview a question | 61 * | edit | Question name | The screen to edit a question | 62 * 63 * @param string $type identifies which type of page this is, e.g. 'Preview'. 64 * @param string $identifier identifies the particular page, e.g. 'My question'. 65 * @return moodle_url the corresponding URL. 66 * @throws Exception with a meaningful error message if the specified page cannot be found. 67 */ 68 protected function resolve_page_instance_url(string $type, string $identifier): moodle_url { 69 switch (strtolower($type)) { 70 case 'course question bank': 71 return new moodle_url('/question/edit.php', 72 ['courseid' => $this->get_course_id($identifier)]); 73 74 case 'course question categories': 75 return new moodle_url('/question/category.php', 76 ['courseid' => $this->get_course_id($identifier)]); 77 78 case 'course question import': 79 return new moodle_url('/question/import.php', 80 ['courseid' => $this->get_course_id($identifier)]); 81 82 case 'course question export': 83 return new moodle_url('/question/export.php', 84 ['courseid' => $this->get_course_id($identifier)]); 85 86 case 'preview': 87 [$questionid, $otheridtype, $otherid] = $this->find_question_by_name($identifier); 88 return new moodle_url('/question/preview.php', 89 ['id' => $questionid, $otheridtype => $otherid]); 90 91 case 'edit': 92 [$questionid, $otheridtype, $otherid] = $this->find_question_by_name($identifier); 93 return new moodle_url('/question/question.php', 94 ['id' => $questionid, $otheridtype => $otherid]); 95 96 default: 97 throw new Exception('Unrecognised core_question page type "' . $type . '."'); 98 } 99 } 100 101 /** 102 * Find a question, and where it is, from the question name. 103 * 104 * This is a helper used by resolve_page_instance_url. 105 * 106 * @param string $questionname 107 * @return array with three elemnets, int question id, a string 'cmid' or 'courseid', 108 * and int either cmid or courseid as applicable. 109 */ 110 protected function find_question_by_name(string $questionname): array { 111 global $DB; 112 $questionid = $DB->get_field('question', 'id', ['name' => $questionname], MUST_EXIST); 113 $question = question_bank::load_question_data($questionid); 114 $context = context_helper::instance_by_id($question->contextid); 115 116 if ($context->contextlevel == CONTEXT_MODULE) { 117 return [$questionid, 'cmid', $context->instanceid]; 118 } else if ($context->contextlevel == CONTEXT_COURSE) { 119 return [$questionid, 'courseid', $context->instanceid]; 120 } else { 121 throw new coding_exception('Unsupported context level ' . $context->contextlevel); 122 } 123 } 124 125 /** 126 * Change the question type of the give question to a type that does not exist. 127 * 128 * This is useful for testing robustness of the code when a question type 129 * has been uninstalled, even though there are still questions of that type 130 * or attempts at them. 131 * 132 * In order to set things up, you probably need to start by generating 133 * questions of a valid type, then using this to change the type once the 134 * data is created. 135 * 136 * @Given question :questionname is changed to simulate being of an uninstalled type 137 * @param string $questionname the question name. 138 */ 139 public function change_question_to_nonexistant_type($questionname) { 140 global $DB; 141 [$id] = $this->find_question_by_name($questionname); 142 143 // Check our assumption. 144 $nonexistanttype = 'invalidqtype'; 145 if (question_bank::is_qtype_installed($nonexistanttype)) { 146 throw new coding_exception('This code assumes that the qtype_' . $nonexistanttype . 147 ' is not a valid plugin name, but that plugin now seems to exist!'); 148 } 149 150 $DB->set_field('question', 'qtype', $nonexistanttype, ['id' => $id]); 151 question_bank::notify_question_edited($id); 152 } 153 154 /** 155 * Forcibly delete a question from the database. 156 * 157 * This is useful for testing robustness of the code when a question 158 * record is no longer in the database, even though it is referred to. 159 * Obviously, this should never happen, but it has been known to in the past 160 * and so we sometimes need to be able to test the code can handle this situation. 161 * 162 * In order to set things up, you probably need to start by generating 163 * a valid questions, then using this to remove it once the data is created. 164 * 165 * @Given question :questionname no longer exists in the database 166 * @param string $questionname the question name. 167 */ 168 public function remove_question_from_db($questionname) { 169 global $DB; 170 [$id] = $this->find_question_by_name($questionname); 171 $DB->delete_records('question', ['id' => $id]); 172 question_bank::notify_question_edited($id); 173 } 174 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body