PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/mod/quiz/accessrule/seb/tests/phpunit/base.php

http://github.com/moodle/moodle
PHP | 321 lines | 166 code | 50 blank | 105 comment | 4 complexity | 98b4d4e60ac66cc4a74e2ecfa199c762 MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause
  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. * Base class for tests. All tests should extend it to get common helper methods.
  18. *
  19. * @package quizaccess_seb
  20. * @author Andrew Madden <andrewmadden@catalyst-au.net>
  21. * @copyright 2019 Catalyst IT
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. namespace quizaccess_seb\tests\phpunit;
  25. use quizaccess_seb\access_manager;
  26. use quizaccess_seb\settings_provider;
  27. defined('MOODLE_INTERNAL') || die();
  28. global $CFG;
  29. require_once($CFG->dirroot . "/mod/quiz/accessrule/seb/rule.php"); // Include plugin rule class.
  30. require_once($CFG->dirroot . "/mod/quiz/mod_form.php"); // Include plugin rule class.
  31. /**
  32. * Base class for tests. All tests should extend it to get common helper methods.
  33. *
  34. * @copyright 2020 Catalyst IT
  35. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36. */
  37. abstract class quizaccess_seb_testcase extends \advanced_testcase {
  38. /** @var \stdClass $course Test course to contain quiz. */
  39. protected $course;
  40. /** @var \stdClass $quiz A test quiz. */
  41. protected $quiz;
  42. /** @var \stdClass $user A test logged-in user. */
  43. protected $user;
  44. /**
  45. * Called before every test.
  46. */
  47. public function setUp() {
  48. parent::setUp();
  49. $this->resetAfterTest();
  50. $this->course = $this->getDataGenerator()->create_course();
  51. }
  52. /**
  53. * Assign a capability to $USER
  54. * The function creates a student $USER if $USER->id is empty
  55. *
  56. * @param string $capability Capability name.
  57. * @param int $contextid Context ID.
  58. * @param int $roleid Role ID.
  59. * @return int The role id - mainly returned for creation, so calling function can reuse it.
  60. */
  61. protected function assign_user_capability($capability, $contextid, $roleid = null) {
  62. global $USER;
  63. // Create a new student $USER if $USER doesn't exist.
  64. if (empty($USER->id)) {
  65. $user = $this->getDataGenerator()->create_user();
  66. $this->setUser($user);
  67. }
  68. if (empty($roleid)) {
  69. $roleid = \create_role('Dummy role', 'dummyrole', 'dummy role description');
  70. }
  71. \assign_capability($capability, CAP_ALLOW, $roleid, $contextid);
  72. \role_assign($roleid, $USER->id, $contextid);
  73. \accesslib_clear_all_caches_for_unit_testing();
  74. return $roleid;
  75. }
  76. /**
  77. * Strip the seb_ prefix from each setting key.
  78. *
  79. * @param \stdClass $settings Object containing settings.
  80. * @return \stdClass The modified settings object.
  81. */
  82. protected function strip_all_prefixes(\stdClass $settings) : \stdClass {
  83. $newsettings = new \stdClass();
  84. foreach ($settings as $name => $setting) {
  85. $newname = preg_replace("/^seb_/", "", $name);
  86. $newsettings->$newname = $setting; // Add new key.
  87. }
  88. return $newsettings;
  89. }
  90. /**
  91. * Creates a file in the user draft area.
  92. *
  93. * @param string $xml
  94. * @return int The user draftarea id
  95. */
  96. protected function create_test_draftarea_file(string $xml) : int {
  97. global $USER;
  98. $itemid = 0;
  99. $usercontext = \context_user::instance($USER->id);
  100. $filerecord = [
  101. 'contextid' => \context_user::instance($USER->id)->id,
  102. 'component' => 'user',
  103. 'filearea' => 'draft',
  104. 'itemid' => $itemid,
  105. 'filepath' => '/',
  106. 'filename' => 'test.xml'
  107. ];
  108. $fs = get_file_storage();
  109. $fs->create_file_from_string($filerecord, $xml);
  110. $draftitemid = 0;
  111. file_prepare_draft_area($draftitemid, $usercontext->id, 'user', 'draft', 0);
  112. return $draftitemid;
  113. }
  114. /**
  115. * Create a file in a modules filearea.
  116. *
  117. * @param string $xml XML content of the file.
  118. * @param string $cmid Course module id.
  119. * @return int Item ID of file.
  120. */
  121. protected function create_module_test_file(string $xml, string $cmid) : int {
  122. $itemid = 0;
  123. $fs = get_file_storage();
  124. $filerecord = [
  125. 'contextid' => \context_module::instance($cmid)->id,
  126. 'component' => 'quizaccess_seb',
  127. 'filearea' => 'filemanager_sebconfigfile',
  128. 'itemid' => $itemid,
  129. 'filepath' => '/',
  130. 'filename' => 'test.xml'
  131. ];
  132. $fs->create_file_from_string($filerecord, $xml);
  133. return $itemid;
  134. }
  135. /**
  136. * Create a test quiz for the specified course.
  137. *
  138. * @param \stdClass $course
  139. * @param int $requiresafeexambrowser How to use SEB for this quiz?
  140. * @return array
  141. */
  142. protected function create_test_quiz($course, $requiresafeexambrowser = settings_provider::USE_SEB_NO) {
  143. $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
  144. $quiz = $quizgenerator->create_instance([
  145. 'course' => $course->id,
  146. 'questionsperpage' => 0,
  147. 'grade' => 100.0,
  148. 'sumgrades' => 2,
  149. 'seb_requiresafeexambrowser' => $requiresafeexambrowser,
  150. ]);
  151. $quiz->seb_showsebdownloadlink = 1;
  152. $quiz->coursemodule = $quiz->cmid;
  153. // Create a couple of questions.
  154. $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
  155. $cat = $questiongenerator->create_question_category();
  156. $saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
  157. quiz_add_quiz_question($saq->id, $quiz);
  158. $numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
  159. quiz_add_quiz_question($numq->id, $quiz);
  160. return $quiz;
  161. }
  162. /**
  163. * Answer questions for a quiz + user.
  164. *
  165. * @param \stdClass $quiz Quiz to attempt.
  166. * @param \stdClass $user A user to attempt the quiz.
  167. * @return array
  168. */
  169. protected function attempt_quiz($quiz, $user) {
  170. $this->setUser($user);
  171. $starttime = time();
  172. $quizobj = \quiz::create($quiz->id, $user->id);
  173. $quba = \question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
  174. $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
  175. // Start the attempt.
  176. $attempt = quiz_create_attempt($quizobj, 1, false, $starttime, false, $user->id);
  177. quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $starttime);
  178. quiz_attempt_save_started($quizobj, $quba, $attempt);
  179. // Answer the questions.
  180. $attemptobj = \quiz_attempt::create($attempt->id);
  181. $tosubmit = [
  182. 1 => ['answer' => 'frog'],
  183. 2 => ['answer' => '3.14'],
  184. ];
  185. $attemptobj->process_submitted_actions($starttime, false, $tosubmit);
  186. // Finish the attempt.
  187. $attemptobj = \quiz_attempt::create($attempt->id);
  188. $attemptobj->process_finish($starttime, false);
  189. $this->setUser();
  190. return [$quizobj, $quba, $attemptobj];
  191. }
  192. /**
  193. * Create test template.
  194. *
  195. * @param string|null $xml Template content.
  196. * @return \quizaccess_seb\template Just created template.
  197. */
  198. public function create_template(string $xml = null) {
  199. $data = [];
  200. if (!is_null($xml)) {
  201. $data['content'] = $xml;
  202. }
  203. return $this->getDataGenerator()->get_plugin_generator('quizaccess_seb')->create_template($data);
  204. }
  205. /**
  206. * Get access manager for testing.
  207. *
  208. * @return \quizaccess_seb\access_manager
  209. */
  210. protected function get_access_manager() {
  211. return new access_manager(new \quiz($this->quiz,
  212. get_coursemodule_from_id('quiz', $this->quiz->cmid), $this->course));
  213. }
  214. /**
  215. * A helper method to make the rule form the currently created quiz and course.
  216. *
  217. * @return \quiz_access_rule_base|null
  218. */
  219. protected function make_rule() {
  220. return \quizaccess_seb::make(
  221. new \quiz($this->quiz, get_coursemodule_from_id('quiz', $this->quiz->cmid), $this->course),
  222. 0,
  223. true
  224. );
  225. }
  226. /**
  227. * A helper method to set up quiz view page.
  228. */
  229. protected function set_up_quiz_view_page() {
  230. global $PAGE;
  231. $page = new \moodle_page();
  232. $page->set_context(\context_module::instance($this->quiz->cmid));
  233. $page->set_course($this->course);
  234. $page->set_pagelayout('standard');
  235. $page->set_pagetype("mod-quiz-view");
  236. $page->set_url('/mod/quiz/view.php?id=' . $this->quiz->cmid);
  237. $PAGE = $page;
  238. }
  239. /**
  240. * Get a test object containing mock test settings.
  241. *
  242. * @return \stdClass Settings.
  243. */
  244. protected function get_test_settings() : \stdClass {
  245. return (object) [
  246. 'quizid' => 1,
  247. 'cmid' => 1,
  248. 'requiresafeexambrowser' => '1',
  249. 'showsebtaskbar' => '1',
  250. 'showwificontrol' => '0',
  251. 'showreloadbutton' => '1',
  252. 'showtime' => '0',
  253. 'showkeyboardlayout' => '1',
  254. 'allowuserquitseb' => '1',
  255. 'quitpassword' => 'test',
  256. 'linkquitseb' => '',
  257. 'userconfirmquit' => '1',
  258. 'enableaudiocontrol' => '1',
  259. 'muteonstartup' => '0',
  260. 'allowspellchecking' => '0',
  261. 'allowreloadinexam' => '1',
  262. 'activateurlfiltering' => '1',
  263. 'filterembeddedcontent' => '0',
  264. 'expressionsallowed' => 'test.com',
  265. 'regexallowed' => '',
  266. 'expressionsblocked' => '',
  267. 'regexblocked' => '',
  268. 'showsebdownloadlink' => '1',
  269. ];
  270. }
  271. }