See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 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 /** 18 * Tests for the quiz_attempt class. 19 * 20 * @package mod_quiz 21 * @category test 22 * @copyright 2014 Tim Hunt 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 require_once($CFG->dirroot . '/mod/quiz/locallib.php'); 30 31 /** 32 * Tests for the quiz_attempt class. 33 * 34 * @copyright 2014 Tim Hunt 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class mod_quiz_attempt_testcase extends advanced_testcase { 38 39 /** 40 * Create quiz and attempt data with layout. 41 * 42 * @param string $layout layout to set. Like quiz attempt.layout. E.g. '1,2,0,3,4,0,'. 43 * @param string $navmethod quiz navigation method (defaults to free) 44 * @return quiz_attempt the new quiz_attempt object 45 */ 46 protected function create_quiz_and_attempt_with_layout($layout, $navmethod = QUIZ_NAVMETHOD_FREE) { 47 $this->resetAfterTest(true); 48 49 // Make a user to do the quiz. 50 $user = $this->getDataGenerator()->create_user(); 51 $course = $this->getDataGenerator()->create_course(); 52 // Make a quiz. 53 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 54 $quiz = $quizgenerator->create_instance(['course' => $course->id, 55 'grade' => 100.0, 'sumgrades' => 2, 'layout' => $layout, 'navmethod' => $navmethod]); 56 57 $quizobj = quiz::create($quiz->id, $user->id); 58 59 60 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); 61 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); 62 63 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 64 $cat = $questiongenerator->create_question_category(); 65 66 $page = 1; 67 foreach (explode(',', $layout) as $slot) { 68 if ($slot == 0) { 69 $page += 1; 70 continue; 71 } 72 73 $question = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]); 74 quiz_add_quiz_question($question->id, $quiz, $page); 75 } 76 77 $timenow = time(); 78 $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $user->id); 79 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); 80 quiz_attempt_save_started($quizobj, $quba, $attempt); 81 82 return quiz_attempt::create($attempt->id); 83 } 84 85 public function test_attempt_url() { 86 $attempt = $this->create_quiz_and_attempt_with_layout('1,2,0,3,4,0,5,6,0'); 87 88 $attemptid = $attempt->get_attempt()->id; 89 $cmid = $attempt->get_cmid(); 90 $url = '/mod/quiz/attempt.php'; 91 $params = ['attempt' => $attemptid, 'cmid' => $cmid, 'page' => 2]; 92 93 $this->assertEquals(new moodle_url($url, $params), $attempt->attempt_url(null, 2)); 94 95 $params['page'] = 1; 96 $this->assertEquals(new moodle_url($url, $params), $attempt->attempt_url(3)); 97 98 $questionattempt = $attempt->get_question_attempt(4); 99 $expecteanchor = $questionattempt->get_outer_question_div_unique_id(); 100 $this->assertEquals(new moodle_url($url, $params, $expecteanchor), $attempt->attempt_url(4)); 101 102 $this->assertEquals(new moodle_url('#'), $attempt->attempt_url(null, 2, 2)); 103 $this->assertEquals(new moodle_url('#'), $attempt->attempt_url(3, -1, 1)); 104 105 $questionattempt = $attempt->get_question_attempt(4); 106 $expecteanchor = $questionattempt->get_outer_question_div_unique_id(); 107 $this->assertEquals(new moodle_url(null, null, $expecteanchor, null), $attempt->attempt_url(4, -1, 1)); 108 109 // Summary page. 110 $url = '/mod/quiz/summary.php'; 111 unset($params['page']); 112 $this->assertEquals(new moodle_url($url, $params), $attempt->summary_url()); 113 114 // Review page. 115 $url = '/mod/quiz/review.php'; 116 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url()); 117 118 $params['page'] = 1; 119 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(3, -1, false)); 120 $this->assertEquals(new moodle_url($url, $params, $expecteanchor), $attempt->review_url(4, -1, false)); 121 122 unset($params['page']); 123 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2, true)); 124 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(1, -1, true)); 125 126 $params['page'] = 2; 127 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2, false)); 128 unset($params['page']); 129 130 $params['showall'] = 0; 131 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 0, false)); 132 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(1, -1, false)); 133 134 $params['page'] = 1; 135 unset($params['showall']); 136 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(3, -1, false)); 137 138 $params['page'] = 2; 139 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2)); 140 $this->assertEquals(new moodle_url('#'), $attempt->review_url(null, -1, null, 0)); 141 142 $questionattempt = $attempt->get_question_attempt(3); 143 $expecteanchor = '#' . $questionattempt->get_outer_question_div_unique_id(); 144 $this->assertEquals(new moodle_url($expecteanchor), $attempt->review_url(3, -1, null, 0)); 145 146 $questionattempt = $attempt->get_question_attempt(4); 147 $expecteanchor = '#' . $questionattempt->get_outer_question_div_unique_id(); 148 $this->assertEquals(new moodle_url($expecteanchor), $attempt->review_url(4, -1, null, 0)); 149 $this->assertEquals(new moodle_url('#'), $attempt->review_url(null, 2, true, 0)); 150 $this->assertEquals(new moodle_url('#'), $attempt->review_url(1, -1, true, 0)); 151 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2, false, 0)); 152 $this->assertEquals(new moodle_url('#'), $attempt->review_url(null, 0, false, 0)); 153 $this->assertEquals(new moodle_url('#'), $attempt->review_url(1, -1, false, 0)); 154 155 $params['page'] = 1; 156 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(3, -1, false, 0)); 157 158 // Setup another attempt. 159 $attempt = $this->create_quiz_and_attempt_with_layout( 160 '1,2,3,4,5,6,7,8,9,10,0,11,12,13,14,15,16,17,18,19,20,0,' . 161 '21,22,23,24,25,26,27,28,29,30,0,31,32,33,34,35,36,37,38,39,40,0,' . 162 '41,42,43,44,45,46,47,48,49,50,0,51,52,53,54,55,56,57,58,59,60,0'); 163 164 $attemptid = $attempt->get_attempt()->id; 165 $cmid = $attempt->get_cmid(); 166 $params = ['attempt' => $attemptid, 'cmid' => $cmid]; 167 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url()); 168 169 $params['page'] = 2; 170 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2)); 171 172 $params['page'] = 1; 173 unset($params['showall']); 174 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(11, -1, false)); 175 176 $questionattempt = $attempt->get_question_attempt(12); 177 $expecteanchor = $questionattempt->get_outer_question_div_unique_id(); 178 $this->assertEquals(new moodle_url($url, $params, $expecteanchor), $attempt->review_url(12, -1, false)); 179 180 $params['showall'] = 1; 181 unset($params['page']); 182 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2, true)); 183 184 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(1, -1, true)); 185 $params['page'] = 2; 186 unset($params['showall']); 187 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2, false)); 188 unset($params['page']); 189 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 0, false)); 190 $params['page'] = 1; 191 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(11, -1, false)); 192 $this->assertEquals(new moodle_url($url, $params, $expecteanchor), $attempt->review_url(12, -1, false)); 193 $params['page'] = 2; 194 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2)); 195 $this->assertEquals(new moodle_url('#'), $attempt->review_url(null, -1, null, 0)); 196 197 $questionattempt = $attempt->get_question_attempt(3); 198 $expecteanchor = $questionattempt->get_outer_question_div_unique_id(); 199 $this->assertEquals(new moodle_url(null, null, $expecteanchor), $attempt->review_url(3, -1, null, 0)); 200 201 $questionattempt = $attempt->get_question_attempt(4); 202 $expecteanchor = $questionattempt->get_outer_question_div_unique_id(); 203 $this->assertEquals(new moodle_url(null, null, $expecteanchor), $attempt->review_url(4, -1, null, 0)); 204 205 $this->assertEquals(new moodle_url('#'), $attempt->review_url(null, 2, true, 0)); 206 $this->assertEquals(new moodle_url('#'), $attempt->review_url(1, -1, true, 0)); 207 208 $params['page'] = 2; 209 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(null, 2, false, 0)); 210 $this->assertEquals(new moodle_url('#'), $attempt->review_url(null, 0, false, 0)); 211 $this->assertEquals(new moodle_url('#'), $attempt->review_url(1, -1, false, 0)); 212 213 $params['page'] = 1; 214 $this->assertEquals(new moodle_url($url, $params), $attempt->review_url(11, -1, false, 0)); 215 } 216 217 /** 218 * Tests attempt page titles when all questions are on a single page. 219 */ 220 public function test_attempt_titles_single() { 221 $attempt = $this->create_quiz_and_attempt_with_layout('1,2,0'); 222 223 // Attempt page. 224 $this->assertEquals('Quiz 1', $attempt->attempt_page_title(0)); 225 226 // Summary page. 227 $this->assertEquals('Quiz 1: Attempt summary', $attempt->summary_page_title()); 228 229 // Review page. 230 $this->assertEquals('Quiz 1: Attempt review', $attempt->review_page_title(0)); 231 } 232 233 /** 234 * Tests attempt page titles when questions are on multiple pages, but are reviewed on a single page. 235 */ 236 public function test_attempt_titles_multiple_single() { 237 $attempt = $this->create_quiz_and_attempt_with_layout('1,2,0,3,4,0,5,6,0'); 238 239 // Attempt page. 240 $this->assertEquals('Quiz 1 (page 1 of 3)', $attempt->attempt_page_title(0)); 241 $this->assertEquals('Quiz 1 (page 2 of 3)', $attempt->attempt_page_title(1)); 242 $this->assertEquals('Quiz 1 (page 3 of 3)', $attempt->attempt_page_title(2)); 243 244 // Summary page. 245 $this->assertEquals('Quiz 1: Attempt summary', $attempt->summary_page_title()); 246 247 // Review page. 248 $this->assertEquals('Quiz 1: Attempt review', $attempt->review_page_title(0, true)); 249 } 250 251 /** 252 * Tests attempt page titles when questions are on multiple pages, and they are reviewed on multiple pages as well. 253 */ 254 public function test_attempt_titles_multiple_multiple() { 255 $attempt = $this->create_quiz_and_attempt_with_layout( 256 '1,2,3,4,5,6,7,8,9,10,0,11,12,13,14,15,16,17,18,19,20,0,' . 257 '21,22,23,24,25,26,27,28,29,30,0,31,32,33,34,35,36,37,38,39,40,0,' . 258 '41,42,43,44,45,46,47,48,49,50,0,51,52,53,54,55,56,57,58,59,60,0'); 259 260 // Attempt page. 261 $this->assertEquals('Quiz 1 (page 1 of 6)', $attempt->attempt_page_title(0)); 262 $this->assertEquals('Quiz 1 (page 2 of 6)', $attempt->attempt_page_title(1)); 263 $this->assertEquals('Quiz 1 (page 6 of 6)', $attempt->attempt_page_title(5)); 264 265 // Summary page. 266 $this->assertEquals('Quiz 1: Attempt summary', $attempt->summary_page_title()); 267 268 // Review page. 269 $this->assertEquals('Quiz 1: Attempt review (page 1 of 6)', $attempt->review_page_title(0)); 270 $this->assertEquals('Quiz 1: Attempt review (page 2 of 6)', $attempt->review_page_title(1)); 271 $this->assertEquals('Quiz 1: Attempt review (page 6 of 6)', $attempt->review_page_title(5)); 272 273 // When all questions are shown. 274 $this->assertEquals('Quiz 1: Attempt review', $attempt->review_page_title(0, true)); 275 $this->assertEquals('Quiz 1: Attempt review', $attempt->review_page_title(1, true)); 276 } 277 278 public function test_is_participant() { 279 global $USER; 280 $this->resetAfterTest(); 281 $this->setAdminUser(); 282 $course = $this->getDataGenerator()->create_course(); 283 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 284 $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student', [], 'manual', 0, 0, ENROL_USER_SUSPENDED); 285 $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id)); 286 $quizobj = quiz::create($quiz->id); 287 288 // Login as student. 289 $this->setUser($student); 290 // Convert to a lesson object. 291 $this->assertEquals(true, $quizobj->is_participant($student->id), 292 'Student is enrolled, active and can participate'); 293 294 // Login as student2. 295 $this->setUser($student2); 296 $this->assertEquals(false, $quizobj->is_participant($student2->id), 297 'Student is enrolled, suspended and can NOT participate'); 298 299 // Login as an admin. 300 $this->setAdminUser(); 301 $this->assertEquals(false, $quizobj->is_participant($USER->id), 302 'Admin is not enrolled and can NOT participate'); 303 304 $this->getDataGenerator()->enrol_user(2, $course->id); 305 $this->assertEquals(true, $quizobj->is_participant($USER->id), 306 'Admin is enrolled and can participate'); 307 308 $this->getDataGenerator()->enrol_user(2, $course->id, [], 'manual', 0, 0, ENROL_USER_SUSPENDED); 309 $this->assertEquals(true, $quizobj->is_participant($USER->id), 310 'Admin is enrolled, suspended and can participate'); 311 } 312 313 /** 314 * Test quiz_prepare_and_start_new_attempt function 315 */ 316 public function test_quiz_prepare_and_start_new_attempt() { 317 global $USER; 318 $this->resetAfterTest(); 319 320 // Create course. 321 $course = $this->getDataGenerator()->create_course(); 322 // Create students. 323 $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 324 $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 325 // Create quiz. 326 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 327 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'grade' => 100.0, 'sumgrades' => 2, 'layout' => '1,0']); 328 // Create question and add it to quiz. 329 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 330 $cat = $questiongenerator->create_question_category(); 331 $question = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]); 332 quiz_add_quiz_question($question->id, $quiz, 1); 333 334 $quizobj = quiz::create($quiz->id); 335 336 // Login as student1. 337 $this->setUser($student1); 338 // Create attempt for student1. 339 $attempt = quiz_prepare_and_start_new_attempt($quizobj, 1, null, false, [], []); 340 $this->assertEquals($student1->id, $attempt->userid); 341 $this->assertEquals(0, $attempt->preview); 342 343 // Login as student2. 344 $this->setUser($student2); 345 // Create attempt for student2. 346 $attempt = quiz_prepare_and_start_new_attempt($quizobj, 1, null, false, [], []); 347 $this->assertEquals($student2->id, $attempt->userid); 348 $this->assertEquals(0, $attempt->preview); 349 350 // Login as admin. 351 $this->setAdminUser(); 352 // Create attempt for student1. 353 $attempt = quiz_prepare_and_start_new_attempt($quizobj, 2, null, false, [], [], $student1->id); 354 $this->assertEquals($student1->id, $attempt->userid); 355 $this->assertEquals(0, $attempt->preview); 356 $student1attempt = $attempt; // Save for extra verification below. 357 // Create attempt for student2. 358 $attempt = quiz_prepare_and_start_new_attempt($quizobj, 2, null, false, [], [], $student2->id); 359 $this->assertEquals($student2->id, $attempt->userid); 360 $this->assertEquals(0, $attempt->preview); 361 // Create attempt for user id that the same with current $USER->id. 362 $attempt = quiz_prepare_and_start_new_attempt($quizobj, 2, null, false, [], [], $USER->id); 363 $this->assertEquals($USER->id, $attempt->userid); 364 $this->assertEquals(1, $attempt->preview); 365 366 // Check that the userid stored in the first step is the user the attempt is for, 367 // not the user who triggered the creation. 368 $quba = question_engine::load_questions_usage_by_activity($student1attempt->uniqueid); 369 $step = $quba->get_question_attempt(1)->get_step(0); 370 $this->assertEquals($student1->id, $step->get_user_id()); 371 } 372 373 /** 374 * Test check_page_access function 375 * @covers \quiz_attempt::check_page_access 376 */ 377 public function test_check_page_access() { 378 $timenow = time(); 379 380 // Free navigation. 381 $attempt = $this->create_quiz_and_attempt_with_layout('1,0,2,0,3,0,4,0,5,0', QUIZ_NAVMETHOD_FREE); 382 383 // Check access. 384 $this->assertTrue($attempt->check_page_access(4)); 385 $this->assertTrue($attempt->check_page_access(3)); 386 $this->assertTrue($attempt->check_page_access(2)); 387 $this->assertTrue($attempt->check_page_access(1)); 388 $this->assertTrue($attempt->check_page_access(0)); 389 $this->assertTrue($attempt->check_page_access(2)); 390 391 // Access page 2. 392 $attempt->set_currentpage(2); 393 $attempt = quiz_attempt::create($attempt->get_attempt()->id); 394 395 // Check access. 396 $this->assertTrue($attempt->check_page_access(0)); 397 $this->assertTrue($attempt->check_page_access(1)); 398 $this->assertTrue($attempt->check_page_access(2)); 399 $this->assertTrue($attempt->check_page_access(3)); 400 $this->assertTrue($attempt->check_page_access(4)); 401 402 // Sequential navigation. 403 $attempt = $this->create_quiz_and_attempt_with_layout('1,0,2,0,3,0,4,0,5,0', QUIZ_NAVMETHOD_SEQ); 404 405 // Check access. 406 $this->assertTrue($attempt->check_page_access(0)); 407 $this->assertTrue($attempt->check_page_access(1)); 408 $this->assertFalse($attempt->check_page_access(2)); 409 $this->assertFalse($attempt->check_page_access(3)); 410 $this->assertFalse($attempt->check_page_access(4)); 411 412 // Access page 1. 413 $attempt->set_currentpage(1); 414 $attempt = quiz_attempt::create($attempt->get_attempt()->id); 415 $this->assertTrue($attempt->check_page_access(1)); 416 417 // Access page 2. 418 $attempt->set_currentpage(2); 419 $attempt = quiz_attempt::create($attempt->get_attempt()->id); 420 $this->assertTrue($attempt->check_page_access(2)); 421 422 $this->assertTrue($attempt->check_page_access(3)); 423 $this->assertFalse($attempt->check_page_access(4)); 424 $this->assertFalse($attempt->check_page_access(1)); 425 } 426 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body