Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
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 * @package core_grades 19 * @category phpunit 20 * @copyright nicolas@moodle.com 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 */ 23 24 defined('MOODLE_INTERNAL') || die(); 25 26 require_once (__DIR__.'/fixtures/lib.php'); 27 28 class core_grade_item_testcase extends grade_base_testcase { 29 public function test_grade_item() { 30 $this->sub_test_grade_item_construct(); 31 $this->sub_test_grade_item_insert(); 32 $this->sub_test_grade_item_delete(); 33 $this->sub_test_grade_item_update(); 34 $this->sub_test_grade_item_load_scale(); 35 $this->sub_test_grade_item_load_outcome(); 36 $this->sub_test_grade_item_qualifies_for_regrading(); 37 $this->sub_test_grade_item_force_regrading(); 38 $this->sub_test_grade_item_fetch(); 39 $this->sub_test_grade_item_fetch_all(); 40 $this->sub_test_grade_item_get_all_finals(); 41 $this->sub_test_grade_item_get_final(); 42 $this->sub_test_grade_item_get_sortorder(); 43 $this->sub_test_grade_item_set_sortorder(); 44 $this->sub_test_grade_item_move_after_sortorder(); 45 $this->sub_test_grade_item_get_name_escaped(); 46 $this->sub_test_grade_item_get_name_unescaped(); 47 $this->sub_test_grade_item_set_parent(); 48 $this->sub_test_grade_item_get_parent_category(); 49 $this->sub_test_grade_item_load_parent_category(); 50 $this->sub_test_grade_item_get_item_category(); 51 $this->sub_test_grade_item_load_item_category(); 52 $this->sub_test_grade_item_regrade_final_grades(); 53 $this->sub_test_grade_item_adjust_raw_grade(); 54 $this->sub_test_grade_item_rescale_grades_keep_percentage(); 55 $this->sub_test_grade_item_set_locked(); 56 $this->sub_test_grade_item_is_locked(); 57 $this->sub_test_grade_item_set_hidden(); 58 $this->sub_test_grade_item_is_hidden(); 59 $this->sub_test_grade_item_is_category_item(); 60 $this->sub_test_grade_item_is_course_item(); 61 $this->sub_test_grade_item_fetch_course_item(); 62 $this->sub_test_grade_item_depends_on(); 63 $this->sub_test_refresh_grades(); 64 $this->sub_test_grade_item_is_calculated(); 65 $this->sub_test_grade_item_set_calculation(); 66 $this->sub_test_grade_item_get_calculation(); 67 $this->sub_test_grade_item_compute(); 68 $this->sub_test_update_final_grade(); 69 $this->sub_test_grade_item_can_control_visibility(); 70 $this->sub_test_grade_item_fix_sortorder(); 71 $this->sub_test_grade_item_created_event(); 72 $this->sub_test_grade_item_updated_event(); 73 } 74 75 protected function sub_test_grade_item_construct() { 76 $params = new stdClass(); 77 78 $params->courseid = $this->courseid; 79 $params->categoryid = $this->grade_categories[1]->id; 80 $params->itemname = 'unittestgradeitem4'; 81 $params->itemtype = 'mod'; 82 $params->itemmodule = 'database'; 83 $params->iteminfo = 'Grade item used for unit testing'; 84 85 $grade_item = new grade_item($params, false); 86 87 $this->assertEquals($params->courseid, $grade_item->courseid); 88 $this->assertEquals($params->categoryid, $grade_item->categoryid); 89 $this->assertEquals($params->itemmodule, $grade_item->itemmodule); 90 } 91 92 protected function sub_test_grade_item_insert() { 93 $grade_item = new grade_item(); 94 $this->assertTrue(method_exists($grade_item, 'insert')); 95 96 $grade_item->courseid = $this->courseid; 97 $grade_item->categoryid = $this->grade_categories[1]->id; 98 $grade_item->itemname = 'unittestgradeitem4'; 99 $grade_item->itemtype = 'mod'; 100 $grade_item->itemmodule = 'quiz'; 101 $grade_item->iteminfo = 'Grade item used for unit testing'; 102 103 $grade_item->insert(); 104 105 $last_grade_item = end($this->grade_items); 106 107 $this->assertEquals($grade_item->id, $last_grade_item->id + 1); 108 $this->assertEquals(18, $grade_item->sortorder); 109 110 // Keep our reference collection the same as what is in the database. 111 $this->grade_items[] = $grade_item; 112 } 113 114 protected function sub_test_grade_item_delete() { 115 global $DB; 116 $grade_item = new grade_item($this->grade_items[7], false); // Use a grade item not touched by previous (or future) tests. 117 $this->assertTrue(method_exists($grade_item, 'delete')); 118 119 // Add two files. 120 $dummy = array( 121 'contextid' => $grade_item->get_context()->id, 122 'component' => GRADE_FILE_COMPONENT, 123 'filearea' => GRADE_HISTORY_FEEDBACK_FILEAREA, 124 'itemid' => 1, 125 'filepath' => '/', 126 'filename' => 'feedback1.txt' 127 ); 128 129 $fs = get_file_storage(); 130 $fs->create_file_from_string($dummy, ''); 131 132 $dummy['itemid'] = 2; 133 $fs->create_file_from_string($dummy, ''); 134 135 $files = $fs->get_area_files($grade_item->get_context()->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 136 // Includes directories. 137 $this->assertCount(4, $files); 138 139 $this->assertTrue($grade_item->delete()); 140 141 $this->assertFalse($DB->get_record('grade_items', array('id' => $grade_item->id))); 142 143 $files = $fs->get_area_files($grade_item->get_context()->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 144 $this->assertEmpty($files); 145 146 // Keep our reference collection the same as the database. 147 unset($this->grade_items[7]); 148 } 149 150 protected function sub_test_grade_item_update() { 151 global $DB; 152 $grade_item = new grade_item($this->grade_items[0], false); 153 $this->assertTrue(method_exists($grade_item, 'update')); 154 155 $grade_item->iteminfo = 'Updated info for this unittest grade_item'; 156 157 $this->assertTrue($grade_item->update()); 158 159 $grade_item->grademin = 14; 160 $this->assertTrue($grade_item->qualifies_for_regrading()); 161 $this->assertTrue($grade_item->update()); 162 163 $iteminfo = $DB->get_field('grade_items', 'iteminfo', array('id' => $this->grade_items[0]->id)); 164 $this->assertEquals($grade_item->iteminfo, $iteminfo); 165 } 166 167 protected function sub_test_grade_item_load_scale() { 168 $grade_item = new grade_item($this->grade_items[2], false); 169 $this->assertTrue(method_exists($grade_item, 'load_scale')); 170 $scale = $grade_item->load_scale(); 171 $this->assertFalse(empty($grade_item->scale)); 172 $this->assertEquals($scale->id, $this->grade_items[2]->scaleid); 173 } 174 175 protected function sub_test_grade_item_load_outcome() { 176 $grade_item = new grade_item($this->grade_items[0], false); 177 $this->assertTrue(method_exists($grade_item, 'load_outcome')); 178 // TODO: add tests. 179 } 180 181 protected function sub_test_grade_item_qualifies_for_regrading() { 182 $grade_item = new grade_item($this->grade_items[3], false); // Use a grade item not touched by previous tests. 183 $this->assertTrue(method_exists($grade_item, 'qualifies_for_regrading')); 184 185 $this->assertFalse($grade_item->qualifies_for_regrading()); 186 187 $grade_item->iteminfo = 'Updated info for this unittest grade_item'; 188 189 $this->assertFalse($grade_item->qualifies_for_regrading()); 190 191 $grade_item->grademin = 14; 192 193 $this->assertTrue($grade_item->qualifies_for_regrading()); 194 } 195 196 protected function sub_test_grade_item_force_regrading() { 197 $grade_item = new grade_item($this->grade_items[3], false); // Use a grade item not touched by previous tests. 198 $this->assertTrue(method_exists($grade_item, 'force_regrading')); 199 200 $this->assertEquals(0, $grade_item->needsupdate); 201 202 $grade_item->force_regrading(); 203 $this->assertEquals(1, $grade_item->needsupdate); 204 $grade_item->update_from_db(); 205 $this->assertEquals(1, $grade_item->needsupdate); 206 } 207 208 protected function sub_test_grade_item_fetch() { 209 $grade_item = new grade_item(); 210 $this->assertTrue(method_exists($grade_item, 'fetch')); 211 212 // Not using $this->grade_items[0] as it's iteminfo was modified by sub_test_grade_item_qualifies_for_regrading(). 213 $grade_item = grade_item::fetch(array('id'=>$this->grade_items[1]->id)); 214 $this->assertEquals($this->grade_items[1]->id, $grade_item->id); 215 $this->assertEquals($this->grade_items[1]->iteminfo, $grade_item->iteminfo); 216 217 $grade_item = grade_item::fetch(array('itemtype'=>$this->grade_items[1]->itemtype, 'itemmodule'=>$this->grade_items[1]->itemmodule)); 218 $this->assertEquals($this->grade_items[1]->id, $grade_item->id); 219 $this->assertEquals($this->grade_items[1]->iteminfo, $grade_item->iteminfo); 220 } 221 222 protected function sub_test_grade_item_fetch_all() { 223 $grade_item = new grade_item(); 224 $this->assertTrue(method_exists($grade_item, 'fetch_all')); 225 226 $grade_items = grade_item::fetch_all(array('courseid'=>$this->courseid)); 227 $this->assertEquals(count($this->grade_items), count($grade_items)-1); // -1 to account for the course grade item. 228 } 229 230 // Retrieve all final scores for a given grade_item. 231 protected function sub_test_grade_item_get_all_finals() { 232 $grade_item = new grade_item($this->grade_items[0], false); 233 $this->assertTrue(method_exists($grade_item, 'get_final')); 234 235 $final_grades = $grade_item->get_final(); 236 $this->assertEquals(3, count($final_grades)); 237 } 238 239 240 // Retrieve all final scores for a specific userid. 241 protected function sub_test_grade_item_get_final() { 242 $grade_item = new grade_item($this->grade_items[0], false); 243 $this->assertTrue(method_exists($grade_item, 'get_final')); 244 $final_grade = $grade_item->get_final($this->user[1]->id); 245 $this->assertEquals($this->grade_grades[0]->finalgrade, $final_grade->finalgrade); 246 } 247 248 protected function sub_test_grade_item_get_sortorder() { 249 $grade_item = new grade_item($this->grade_items[0], false); 250 $this->assertTrue(method_exists($grade_item, 'get_sortorder')); 251 $sortorder = $grade_item->get_sortorder(); 252 $this->assertEquals($this->grade_items[0]->sortorder, $sortorder); 253 } 254 255 protected function sub_test_grade_item_set_sortorder() { 256 $grade_item = new grade_item($this->grade_items[0], false); 257 $this->assertTrue(method_exists($grade_item, 'set_sortorder')); 258 $grade_item->set_sortorder(999); 259 $this->assertEquals($grade_item->sortorder, 999); 260 } 261 262 protected function sub_test_grade_item_move_after_sortorder() { 263 $grade_item = new grade_item($this->grade_items[0], false); 264 $this->assertTrue(method_exists($grade_item, 'move_after_sortorder')); 265 $grade_item->move_after_sortorder(5); 266 $this->assertEquals($grade_item->sortorder, 6); 267 268 $grade_item = grade_item::fetch(array('id'=>$this->grade_items[0]->id)); 269 $this->assertEquals($grade_item->sortorder, 6); 270 271 $after = grade_item::fetch(array('id'=>$this->grade_items[6]->id)); 272 $this->assertEquals($after->sortorder, 8); 273 } 274 275 /** 276 * Tests the getter of the item name with escaped HTML. 277 */ 278 protected function sub_test_grade_item_get_name_escaped() { 279 $gradeitem = new grade_item($this->grade_items[0], false); 280 $this->assertTrue(method_exists($gradeitem, 'get_name')); 281 $this->assertEquals(format_string($this->grade_items[0]->itemname, true, ['escape' => true]), 282 $gradeitem->get_name(false, true)); 283 } 284 285 /** 286 * Tests the getter of the item name with unescaped HTML. 287 */ 288 protected function sub_test_grade_item_get_name_unescaped() { 289 $gradeitem = new grade_item($this->grade_items[0], false); 290 $this->assertTrue(method_exists($gradeitem, 'get_name')); 291 $this->assertEquals(format_string($this->grade_items[0]->itemname, true, ['escape' => false]), 292 $gradeitem->get_name(false, false)); 293 } 294 295 protected function sub_test_grade_item_set_parent() { 296 $grade_item = new grade_item($this->grade_items[0], false); 297 $this->assertTrue(method_exists($grade_item, 'set_parent')); 298 299 $old = $grade_item->get_parent_category(); 300 $new = new grade_category($this->grade_categories[3], false); 301 $new_item = $new->get_grade_item(); 302 303 $this->assertTrue($grade_item->set_parent($new->id)); 304 305 $new_item->update_from_db(); 306 $grade_item->update_from_db(); 307 308 $this->assertEquals($grade_item->categoryid, $new->id); 309 } 310 311 protected function sub_test_grade_item_get_parent_category() { 312 $grade_item = new grade_item($this->grade_items[0], false); 313 $this->assertTrue(method_exists($grade_item, 'get_parent_category')); 314 315 $category = $grade_item->get_parent_category(); 316 $this->assertEquals($this->grade_categories[1]->fullname, $category->fullname); 317 } 318 319 protected function sub_test_grade_item_load_parent_category() { 320 $grade_item = new grade_item($this->grade_items[0], false); 321 $this->assertTrue(method_exists($grade_item, 'load_parent_category')); 322 323 $category = $grade_item->load_parent_category(); 324 $this->assertEquals($this->grade_categories[1]->fullname, $category->fullname); 325 $this->assertEquals($this->grade_categories[1]->fullname, $grade_item->parent_category->fullname); 326 } 327 328 protected function sub_test_grade_item_get_item_category() { 329 $grade_item = new grade_item($this->grade_items[3], false); 330 $this->assertTrue(method_exists($grade_item, 'get_item_category')); 331 332 $category = $grade_item->get_item_category(); 333 $this->assertEquals($this->grade_categories[0]->fullname, $category->fullname); 334 } 335 336 protected function sub_test_grade_item_load_item_category() { 337 $grade_item = new grade_item($this->grade_items[3], false); 338 $this->assertTrue(method_exists($grade_item, 'load_item_category')); 339 340 $category = $grade_item->load_item_category(); 341 $this->assertEquals($this->grade_categories[0]->fullname, $category->fullname); 342 $this->assertEquals($this->grade_categories[0]->fullname, $grade_item->item_category->fullname); 343 } 344 345 protected function sub_test_grade_item_regrade_final_grades() { 346 $grade_item = new grade_item($this->grade_items[0], false); 347 $this->assertTrue(method_exists($grade_item, 'regrade_final_grades')); 348 $this->assertEquals(true, $grade_item->regrade_final_grades()); 349 // TODO: add more tests. 350 } 351 352 protected function sub_test_grade_item_adjust_raw_grade() { 353 $grade_item = new grade_item($this->grade_items[2], false); // Anything but assignment module! 354 $this->assertTrue(method_exists($grade_item, 'adjust_raw_grade')); 355 356 $grade_raw = new stdClass(); 357 $grade_raw->rawgrade = 40; 358 $grade_raw->grademax = 100; 359 $grade_raw->grademin = 0; 360 361 $grade_item->gradetype = GRADE_TYPE_VALUE; 362 $grade_item->multfactor = 1; 363 $grade_item->plusfactor = 0; 364 $grade_item->grademax = 50; 365 $grade_item->grademin = 0; 366 367 $original_grade_raw = clone($grade_raw); 368 $original_grade_item = clone($grade_item); 369 370 $this->assertEquals(20, $grade_item->adjust_raw_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax)); 371 372 // Try a larger maximum grade. 373 $grade_item->grademax = 150; 374 $grade_item->grademin = 0; 375 $this->assertEquals(60, $grade_item->adjust_raw_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax)); 376 377 // Try larger minimum grade. 378 $grade_item->grademin = 50; 379 380 $this->assertEquals(90, $grade_item->adjust_raw_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax)); 381 382 // Rescaling from a small scale (0-50) to a larger scale (0-100). 383 $grade_raw->grademax = 50; 384 $grade_raw->grademin = 0; 385 $grade_item->grademax = 100; 386 $grade_item->grademin = 0; 387 388 $this->assertEquals(80, $grade_item->adjust_raw_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax)); 389 390 // Rescaling from a small scale (0-50) to a larger scale with offset (40-100). 391 $grade_item->grademax = 100; 392 $grade_item->grademin = 40; 393 394 $this->assertEquals(88, $grade_item->adjust_raw_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax)); 395 396 // Try multfactor and plusfactor. 397 $grade_raw = clone($original_grade_raw); 398 $grade_item = clone($original_grade_item); 399 $grade_item->multfactor = 1.23; 400 $grade_item->plusfactor = 3; 401 402 $this->assertEquals(27.6, $grade_item->adjust_raw_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax)); 403 404 // Try multfactor below 0 and a negative plusfactor. 405 $grade_raw = clone($original_grade_raw); 406 $grade_item = clone($original_grade_item); 407 $grade_item->multfactor = 0.23; 408 $grade_item->plusfactor = -3; 409 410 $this->assertEquals(round(1.6), round($grade_item->adjust_raw_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax))); 411 } 412 413 protected function sub_test_grade_item_rescale_grades_keep_percentage() { 414 global $DB; 415 $gradeitem = new grade_item($this->grade_items[10], false); // 10 is the manual grade item. 416 417 // Create some grades to go with the grade item. 418 $gradeids = array(); 419 $grade = new stdClass(); 420 $grade->itemid = $gradeitem->id; 421 $grade->userid = $this->user[2]->id; 422 $grade->finalgrade = 10; 423 $grade->rawgrademax = $gradeitem->grademax; 424 $grade->rawgrademin = $gradeitem->grademin; 425 $grade->timecreated = time(); 426 $grade->timemodified = time(); 427 $gradeids[] = $DB->insert_record('grade_grades', $grade); 428 429 $grade->userid = $this->user[3]->id; 430 $grade->finalgrade = 50; 431 $grade->rawgrademax = $gradeitem->grademax; 432 $grade->rawgrademin = $gradeitem->grademin; 433 $gradeids[] = $DB->insert_record('grade_grades', $grade); 434 435 // Run the function. 436 $gradeitem->grademax = 33; 437 $gradeitem->grademin = 3; 438 $gradeitem->update(); 439 $gradeitem->rescale_grades_keep_percentage(0, 100, 3, 33, 'test'); 440 441 // Check that the grades were updated to match the grade item. 442 $grade = $DB->get_record('grade_grades', array('id' => $gradeids[0])); 443 $this->assertEqualsWithDelta($gradeitem->grademax, $grade->rawgrademax, 0.0001, 'Max grade mismatch'); 444 $this->assertEqualsWithDelta($gradeitem->grademin, $grade->rawgrademin, 0.0001, 'Min grade mismatch'); 445 $this->assertEqualsWithDelta(6, $grade->finalgrade, 0.0001, 'Min grade mismatch'); 446 447 $grade = $DB->get_record('grade_grades', array('id' => $gradeids[1])); 448 $this->assertEqualsWithDelta($gradeitem->grademax, $grade->rawgrademax, 0.0001, 'Max grade mismatch'); 449 $this->assertEqualsWithDelta($gradeitem->grademin, $grade->rawgrademin, 0.0001, 'Min grade mismatch'); 450 $this->assertEqualsWithDelta(18, $grade->finalgrade, 0.0001, 'Min grade mismatch'); 451 } 452 453 protected function sub_test_grade_item_set_locked() { 454 // Getting a grade_item from the DB as set_locked() will fail if the grade items needs to be updated 455 // also needs to have at least one grade_grade or $grade_item->get_final(1) returns null. 456 // $grade_item = new grade_item($this->grade_items[8]); 457 $grade_item = grade_item::fetch(array('id'=>$this->grade_items[8]->id)); 458 459 $this->assertTrue(method_exists($grade_item, 'set_locked')); 460 461 $grade_grade = new grade_grade($grade_item->get_final($this->user[1]->id), false); 462 $this->assertTrue(empty($grade_item->locked));// Not locked. 463 $this->assertTrue(empty($grade_grade->locked));// Not locked. 464 465 $this->assertTrue($grade_item->set_locked(true, true, false)); 466 $grade_grade = new grade_grade($grade_item->get_final($this->user[1]->id), false); 467 468 $this->assertFalse(empty($grade_item->locked));// Locked. 469 $this->assertFalse(empty($grade_grade->locked)); // Individual grades should be locked too. 470 471 $this->assertTrue($grade_item->set_locked(false, true, false)); 472 $grade = new grade_grade($grade_item->get_final($this->user[1]->id), false); 473 474 $this->assertTrue(empty($grade_item->locked)); 475 $this->assertTrue(empty($grade->locked)); // Individual grades should be unlocked too. 476 } 477 478 protected function sub_test_grade_item_is_locked() { 479 $grade_item = new grade_item($this->grade_items[10], false); 480 $this->assertTrue(method_exists($grade_item, 'is_locked')); 481 482 $this->assertFalse($grade_item->is_locked()); 483 $this->assertFalse($grade_item->is_locked($this->user[1]->id)); 484 $this->assertTrue($grade_item->set_locked(true, true, false)); 485 $this->assertTrue($grade_item->is_locked()); 486 $this->assertTrue($grade_item->is_locked($this->user[1]->id)); 487 } 488 489 protected function sub_test_grade_item_set_hidden() { 490 $grade_item = new grade_item($this->grade_items[0], false); 491 $this->assertTrue(method_exists($grade_item, 'set_hidden')); 492 493 $grade = new grade_grade($grade_item->get_final($this->user[1]->id), false); 494 $this->assertEquals(0, $grade_item->hidden); 495 $this->assertEquals(0, $grade->hidden); 496 497 $grade_item->set_hidden(666, true); 498 $grade = new grade_grade($grade_item->get_final($this->user[1]->id), false); 499 500 $this->assertEquals(666, $grade_item->hidden); 501 $this->assertEquals(666, $grade->hidden); 502 } 503 504 protected function sub_test_grade_item_is_hidden() { 505 $grade_item = new grade_item($this->grade_items[0], false); 506 $this->assertTrue(method_exists($grade_item, 'is_hidden')); 507 508 $this->assertFalse($grade_item->is_hidden()); 509 $this->assertFalse($grade_item->is_hidden(1)); 510 511 $grade_item->set_hidden(1); 512 $this->assertTrue($grade_item->is_hidden()); 513 $this->assertTrue($grade_item->is_hidden(1)); 514 515 $grade_item->set_hidden(666); 516 $this->assertFalse($grade_item->is_hidden()); 517 $this->assertFalse($grade_item->is_hidden(1)); 518 519 $grade_item->set_hidden(time()+666); 520 $this->assertTrue($grade_item->is_hidden()); 521 $this->assertTrue($grade_item->is_hidden(1)); 522 } 523 524 protected function sub_test_grade_item_is_category_item() { 525 $grade_item = new grade_item($this->grade_items[3], false); 526 $this->assertTrue(method_exists($grade_item, 'is_category_item')); 527 $this->assertTrue($grade_item->is_category_item()); 528 } 529 530 protected function sub_test_grade_item_is_course_item() { 531 $grade_item = grade_item::fetch_course_item($this->courseid); 532 $this->assertTrue(method_exists($grade_item, 'is_course_item')); 533 $this->assertTrue($grade_item->is_course_item()); 534 } 535 536 protected function sub_test_grade_item_fetch_course_item() { 537 $grade_item = grade_item::fetch_course_item($this->courseid); 538 $this->assertTrue(method_exists($grade_item, 'fetch_course_item')); 539 $this->assertEquals($grade_item->itemtype, 'course'); 540 } 541 542 protected function sub_test_grade_item_depends_on() { 543 global $CFG; 544 545 $origenableoutcomes = $CFG->enableoutcomes; 546 $CFG->enableoutcomes = 0; 547 $grade_item = new grade_item($this->grade_items[1], false); 548 549 // Calculated grade dependency. 550 $deps = $grade_item->depends_on(); 551 sort($deps, SORT_NUMERIC); // For comparison. 552 $this->assertEquals(array($this->grade_items[0]->id), $deps); 553 554 // Simulate depends on returns none when locked. 555 $grade_item->locked = time(); 556 $grade_item->update(); 557 $deps = $grade_item->depends_on(); 558 sort($deps, SORT_NUMERIC); // For comparison. 559 $this->assertEquals(array(), $deps); 560 561 // Category dependency. 562 $grade_item = new grade_item($this->grade_items[3], false); 563 $deps = $grade_item->depends_on(); 564 sort($deps, SORT_NUMERIC); // For comparison. 565 $res = array($this->grade_items[4]->id, $this->grade_items[5]->id); 566 $this->assertEquals($res, $deps); 567 } 568 569 protected function scales_outcomes_test_grade_item_depends_on() { 570 $CFG->enableoutcomes = 1; 571 $origgradeincludescalesinaggregation = $CFG->grade_includescalesinaggregation; 572 $CFG->grade_includescalesinaggregation = 1; 573 574 // Scale item in category with $CFG->grade_includescalesinaggregation = 1. 575 $grade_item = new grade_item($this->grade_items[14], false); 576 $deps = $grade_item->depends_on(); 577 sort($deps, SORT_NUMERIC); 578 $res = array($this->grade_items[16]->id); 579 $this->assertEquals($res, $deps); 580 581 // Scale item in category with $CFG->grade_includescalesinaggregation = 0. 582 $CFG->grade_includescalesinaggregation = 0; 583 $grade_item = new grade_item($this->grade_items[14], false); 584 $deps = $grade_item->depends_on(); 585 $res = array(); 586 $this->assertEquals($res, $deps); 587 $CFG->grade_includescalesinaggregation = 1; 588 589 // Outcome item in category with outcomes disabled. 590 $CFG->enableoutcomes = 0; 591 $grade_item = new grade_item($this->grade_items[14], false); 592 $deps = $grade_item->depends_on(); 593 sort($deps, SORT_NUMERIC); 594 $res = array($this->grade_items[16]->id, $this->grade_items[17]->id); 595 $this->assertEquals($res, $deps); 596 597 $CFG->enableoutcomes = $origenableoutcomes; 598 $CFG->grade_includescalesinaggregation = $origgradeincludescalesinaggregation; 599 } 600 601 protected function sub_test_refresh_grades() { 602 // Testing with the grade item for a mod_assignment instance. 603 $grade_item = new grade_item($this->grade_items[0], false); 604 $this->assertTrue(method_exists($grade_item, 'refresh_grades')); 605 $this->assertTrue($grade_item->refresh_grades()); 606 607 // Break the grade item and check error handling. 608 $grade_item->iteminstance = 123456789; 609 $this->assertFalse($grade_item->refresh_grades()); 610 $this->assertDebuggingCalled(); 611 } 612 613 protected function sub_test_grade_item_is_calculated() { 614 $grade_item = new grade_item($this->grade_items[1], false); 615 $this->assertTrue(method_exists($grade_item, 'is_calculated')); 616 $this->assertTrue($grade_item->is_calculated()); 617 618 $grade_item = new grade_item($this->grade_items[0], false); 619 $this->assertFalse($grade_item->is_calculated()); 620 } 621 622 protected function sub_test_grade_item_set_calculation() { 623 $grade_item = new grade_item($this->grade_items[1], false); 624 $this->assertTrue(method_exists($grade_item, 'set_calculation')); 625 $grade_itemsource = new grade_item($this->grade_items[0], false); 626 627 $grade_item->set_calculation('=[['.$grade_itemsource->idnumber.']]'); 628 629 $this->assertTrue(!empty($grade_item->needsupdate)); 630 $this->assertEquals('=##gi'.$grade_itemsource->id.'##', $grade_item->calculation); 631 } 632 633 protected function sub_test_grade_item_get_calculation() { 634 $grade_item = new grade_item($this->grade_items[1], false); 635 $this->assertTrue(method_exists($grade_item, 'get_calculation')); 636 $grade_itemsource = new grade_item($this->grade_items[0], false); 637 638 $denormalizedformula = str_replace('##gi'.$grade_itemsource->id.'##', '[['.$grade_itemsource->idnumber.']]', $this->grade_items[1]->calculation); 639 640 $formula = $grade_item->get_calculation(); 641 $this->assertTrue(!empty($grade_item->needsupdate)); 642 $this->assertEquals($denormalizedformula, $formula); 643 } 644 645 public function sub_test_grade_item_compute() { 646 $grade_item = grade_item::fetch(array('id'=>$this->grade_items[1]->id)); 647 $this->assertTrue(method_exists($grade_item, 'compute')); 648 649 // Check the grade_grades in the array match those in the DB then delete $this->grade_items[1]'s grade_grades. 650 $this->grade_grades[3] = grade_grade::fetch(array('id'=>$this->grade_grades[3]->id)); 651 $grade_grade = grade_grade::fetch(array('id'=>$this->grade_grades[3]->id)); 652 $grade_grade->delete(); 653 654 $this->grade_grades[4] = grade_grade::fetch(array('id'=>$this->grade_grades[4]->id)); 655 $grade_grade = grade_grade::fetch(array('id'=>$this->grade_grades[4]->id)); 656 $grade_grade->delete(); 657 658 $this->grade_grades[5] = grade_grade::fetch(array('id'=>$this->grade_grades[5]->id)); 659 $grade_grade = grade_grade::fetch(array('id'=>$this->grade_grades[5]->id)); 660 $grade_grade->delete(); 661 662 // Recalculate the grades (its a calculation so pulls values from other grade_items) and reinsert them. 663 $grade_item->compute(); 664 665 $grade_grade = grade_grade::fetch(array('userid'=>$this->grade_grades[3]->userid, 'itemid'=>$this->grade_grades[3]->itemid)); 666 $this->assertEquals($this->grade_grades[3]->finalgrade, $grade_grade->finalgrade); 667 668 $grade_grade = grade_grade::fetch(array('userid'=>$this->grade_grades[4]->userid, 'itemid'=>$this->grade_grades[4]->itemid)); 669 $this->assertEquals($this->grade_grades[4]->finalgrade, $grade_grade->finalgrade); 670 671 $grade_grade = grade_grade::fetch(array('userid'=>$this->grade_grades[5]->userid, 'itemid'=>$this->grade_grades[5]->itemid)); 672 $this->assertEquals($this->grade_grades[5]->finalgrade, $grade_grade->finalgrade); 673 } 674 675 protected function sub_test_update_final_grade() { 676 677 // MDL-31713 Check that min and max are set on the grade_grade instance 678 // if the grade is overridden before the activity has supplied a grade. 679 $min = 2; 680 $max = 8; 681 682 // Create a brand new grade item. 683 $grade_item = new grade_item(); 684 $this->assertTrue(method_exists($grade_item, 'insert')); 685 686 $grade_item->courseid = $this->courseid; 687 $grade_item->categoryid = $this->grade_categories[1]->id; 688 $grade_item->itemname = 'brand new unit test grade item'; 689 $grade_item->itemtype = 'mod'; 690 $grade_item->itemmodule = 'quiz'; 691 $grade_item->iteminfo = 'Grade item used for unit testing'; 692 $grade_item->iteminstance = $this->activities[7]->id; 693 $grade_item->grademin = $min; 694 $grade_item->grademax = $max; 695 $grade_item->insert(); 696 697 // Override the student grade. 698 $grade_item->update_final_grade($this->user[1]->id, 7, 'gradebook', '', FORMAT_MOODLE); 699 700 // Check the student's grade has the correct min and max grade. 701 $grade_grade = grade_grade::fetch(array('userid'=>$this->user[1]->id, 'itemid'=>$grade_item->id)); 702 $this->assertEquals($min, $grade_grade->rawgrademin); 703 $this->assertEquals($max, $grade_grade->rawgrademax); 704 } 705 706 protected function sub_test_grade_item_can_control_visibility() { 707 // Grade item 0 == Course module 0 == Assignment. 708 $grade_item = new grade_item($this->grade_items[0], false); 709 $this->assertTrue($grade_item->can_control_visibility()); 710 711 // Grade item == Course module 7 == Quiz. 712 $grade_item = new grade_item($this->grade_items[11], false); 713 $this->assertFalse($grade_item->can_control_visibility()); 714 } 715 716 /** 717 * Test the {@link grade_item::fix_duplicate_sortorder() function with 718 * faked duplicate sortorder data. 719 */ 720 public function sub_test_grade_item_fix_sortorder() { 721 global $DB; 722 723 $this->resetAfterTest(true); 724 725 // Each set is used for filling the db with fake data and will be representing the result of query: 726 // "SELECT sortorder from {grade_items} WHERE courseid=? ORDER BY id". 727 $testsets = array( 728 // Items that need no action. 729 array(1,2,3), 730 array(5,6,7), 731 array(7,6,1,3,2,5), 732 // Items with sortorder duplicates 733 array(1,2,2,3,3,4,5), 734 // Only one sortorder duplicate. 735 array(1,1), 736 array(3,3), 737 // Non-sequential sortorders with one or multiple duplicates. 738 array(3,3,7,5,6,6,9,10,8,3), 739 array(7,7,3), 740 array(3,4,5,3,5,4,7,1) 741 ); 742 $origsequence = array(); 743 744 // Generate the data and remember the initial sequence or items. 745 foreach ($testsets as $testset) { 746 $course = $this->getDataGenerator()->create_course(); 747 foreach ($testset as $sortorder) { 748 $this->insert_fake_grade_item_sortorder($course->id, $sortorder); 749 } 750 $DB->get_records('grade_items'); 751 $origsequence[$course->id] = $DB->get_fieldset_sql("SELECT id FROM {grade_items} ". 752 "WHERE courseid = ? ORDER BY sortorder, id", array($course->id)); 753 } 754 755 $duplicatedetectionsql = "SELECT courseid, sortorder 756 FROM {grade_items} 757 WHERE courseid = :courseid 758 GROUP BY courseid, sortorder 759 HAVING COUNT(id) > 1"; 760 761 // Do the work. 762 foreach ($origsequence as $courseid => $ignore) { 763 grade_item::fix_duplicate_sortorder($courseid); 764 // Verify that no duplicates are left in the database. 765 $dupes = $DB->record_exists_sql($duplicatedetectionsql, array('courseid' => $courseid)); 766 $this->assertFalse($dupes); 767 } 768 769 // Verify that sequences are exactly the same as they were before upgrade script. 770 $idx = 0; 771 foreach ($origsequence as $courseid => $sequence) { 772 if (count(($testsets[$idx])) == count(array_unique($testsets[$idx]))) { 773 // If there were no duplicates for this course verify that sortorders are not modified. 774 $newsortorders = $DB->get_fieldset_sql("SELECT sortorder from {grade_items} WHERE courseid=? ORDER BY id", array($courseid)); 775 $this->assertEquals($testsets[$idx], $newsortorders); 776 } 777 $newsequence = $DB->get_fieldset_sql("SELECT id FROM {grade_items} ". 778 "WHERE courseid = ? ORDER BY sortorder, id", array($courseid)); 779 $this->assertEquals($sequence, $newsequence, 780 "Sequences do not match for test set $idx : ".join(',', $testsets[$idx])); 781 $idx++; 782 } 783 } 784 785 /** 786 * Populate some fake grade items into the database with specified 787 * sortorder and course id. 788 * 789 * NOTE: This function doesn't make much attempt to respect the 790 * gradebook internals, its simply used to fake some data for 791 * testing the upgradelib function. Please don't use it for other 792 * purposes. 793 * 794 * @param int $courseid id of course 795 * @param int $sortorder numeric sorting order of item 796 * @return stdClass grade item object from the database. 797 */ 798 private function insert_fake_grade_item_sortorder($courseid, $sortorder) { 799 global $DB, $CFG; 800 require_once($CFG->libdir.'/gradelib.php'); 801 802 $item = new stdClass(); 803 $item->courseid = $courseid; 804 $item->sortorder = $sortorder; 805 $item->gradetype = GRADE_TYPE_VALUE; 806 $item->grademin = 30; 807 $item->grademax = 110; 808 $item->itemnumber = 1; 809 $item->iteminfo = ''; 810 $item->timecreated = time(); 811 $item->timemodified = time(); 812 813 $item->id = $DB->insert_record('grade_items', $item); 814 815 return $DB->get_record('grade_items', array('id' => $item->id)); 816 } 817 818 public function test_set_aggregation_fields_for_aggregation() { 819 $course = $this->getDataGenerator()->create_course(); 820 $gi = new grade_item(array('courseid' => $course->id, 'itemtype' => 'manual'), false); 821 822 $methods = array(GRADE_AGGREGATE_MEAN, GRADE_AGGREGATE_MEDIAN, GRADE_AGGREGATE_MIN, GRADE_AGGREGATE_MAX, 823 GRADE_AGGREGATE_MODE, GRADE_AGGREGATE_WEIGHTED_MEAN, GRADE_AGGREGATE_WEIGHTED_MEAN2, 824 GRADE_AGGREGATE_EXTRACREDIT_MEAN, GRADE_AGGREGATE_SUM); 825 826 // Switching from and to the same aggregation using the defaults. 827 foreach ($methods as $method) { 828 $defaults = grade_category::get_default_aggregation_coefficient_values($method); 829 $gi->aggregationcoef = $defaults['aggregationcoef']; 830 $gi->aggregationcoef2 = $defaults['aggregationcoef2']; 831 $gi->weightoverride = $defaults['weightoverride']; 832 $this->assertFalse($gi->set_aggregation_fields_for_aggregation($method, $method)); 833 $this->assertEquals($defaults['aggregationcoef'], $gi->aggregationcoef); 834 $this->assertEquals($defaults['aggregationcoef2'], $gi->aggregationcoef2); 835 $this->assertEquals($defaults['weightoverride'], $gi->weightoverride); 836 } 837 838 // Extra credit is kept across aggregation methods that support it. 839 foreach ($methods as $from) { 840 $fromsupportsec = grade_category::aggregation_uses_extracredit($from); 841 $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); 842 843 foreach ($methods as $to) { 844 $tosupportsec = grade_category::aggregation_uses_extracredit($to); 845 $todefaults = grade_category::get_default_aggregation_coefficient_values($to); 846 847 // Set the item to be extra credit, if supported. 848 if ($fromsupportsec) { 849 $gi->aggregationcoef = 1; 850 } else { 851 $gi->aggregationcoef = $fromdefaults['aggregationcoef']; 852 } 853 854 // We ignore those fields, we know it is never used for extra credit. 855 $gi->aggregationcoef2 = $todefaults['aggregationcoef2']; 856 $gi->weightoverride = $todefaults['weightoverride']; 857 858 if ($fromsupportsec && $tosupportsec) { 859 $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 860 $this->assertEquals(1, $gi->aggregationcoef); 861 862 } else if ($fromsupportsec && !$tosupportsec) { 863 if ($to == GRADE_AGGREGATE_WEIGHTED_MEAN) { 864 // Special case, aggregationcoef is used but for weights. 865 $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 866 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 867 } else { 868 $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 869 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 870 } 871 } else { 872 // The source does not support extra credit, everything will be reset. 873 if (($from == GRADE_AGGREGATE_WEIGHTED_MEAN || $to == GRADE_AGGREGATE_WEIGHTED_MEAN) && $from != $to) { 874 // Special case, aggregationcoef is used but for weights. 875 $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 876 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 877 } else { 878 $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 879 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 880 } 881 } 882 } 883 } 884 885 // Extra credit can be higher than one for GRADE_AGGREGATE_EXTRACREDIT_MEAN, but will be normalised for others. 886 $from = GRADE_AGGREGATE_EXTRACREDIT_MEAN; 887 $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); 888 889 foreach ($methods as $to) { 890 if (!grade_category::aggregation_uses_extracredit($to)) { 891 continue; 892 } 893 894 $todefaults = grade_category::get_default_aggregation_coefficient_values($to); 895 $gi->aggregationcoef = 8; 896 897 // Ignore those fields, they are not used for extra credit. 898 $gi->aggregationcoef2 = $todefaults['aggregationcoef2']; 899 $gi->weightoverride = $todefaults['weightoverride']; 900 901 if ($to == $from) { 902 $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 903 $this->assertEquals(8, $gi->aggregationcoef); 904 } else { 905 $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 906 $this->assertEquals(1, $gi->aggregationcoef); 907 } 908 } 909 910 // Weights are reset. 911 $from = GRADE_AGGREGATE_SUM; 912 $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); 913 914 $gi->aggregationcoef = $fromdefaults['aggregationcoef']; 915 $gi->aggregationcoef2 = 0.321; 916 $gi->weightoverride = $fromdefaults['weightoverride']; 917 918 $to = GRADE_AGGREGATE_WEIGHTED_MEAN; 919 $todefaults = grade_category::get_default_aggregation_coefficient_values($to); 920 921 $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 922 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 923 $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); 924 $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); 925 926 $gi->aggregationcoef = $fromdefaults['aggregationcoef']; 927 $gi->aggregationcoef2 = 0.321; 928 $gi->weightoverride = $fromdefaults['weightoverride']; 929 930 $to = GRADE_AGGREGATE_SUM; 931 $todefaults = grade_category::get_default_aggregation_coefficient_values($to); 932 933 $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 934 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 935 $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); 936 $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); 937 938 // Weight is kept when using SUM with weight override. 939 $from = GRADE_AGGREGATE_SUM; 940 $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); 941 942 $gi->aggregationcoef = $fromdefaults['aggregationcoef']; 943 $gi->aggregationcoef2 = 0.321; 944 $gi->weightoverride = 1; 945 946 $to = GRADE_AGGREGATE_SUM; 947 $todefaults = grade_category::get_default_aggregation_coefficient_values($to); 948 949 $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 950 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 951 $this->assertEquals(0.321, $gi->aggregationcoef2); 952 $this->assertEquals(1, $gi->weightoverride); 953 954 $gi->aggregationcoef2 = 0.321; 955 $gi->aggregationcoef = $fromdefaults['aggregationcoef']; 956 $gi->weightoverride = 1; 957 958 $to = GRADE_AGGREGATE_WEIGHTED_MEAN; 959 $todefaults = grade_category::get_default_aggregation_coefficient_values($to); 960 961 $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 962 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 963 $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); 964 $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); 965 966 // Weight is kept when staying in weighted mean. 967 $from = GRADE_AGGREGATE_WEIGHTED_MEAN; 968 $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); 969 970 $gi->aggregationcoef = 18; 971 $gi->aggregationcoef2 = $fromdefaults['aggregationcoef2']; 972 $gi->weightoverride = $fromdefaults['weightoverride']; 973 974 $to = GRADE_AGGREGATE_WEIGHTED_MEAN; 975 $todefaults = grade_category::get_default_aggregation_coefficient_values($to); 976 977 $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 978 $this->assertEquals(18, $gi->aggregationcoef); 979 $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); 980 $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); 981 982 $gi->aggregationcoef = 18; 983 $gi->aggregationcoef2 = $fromdefaults['aggregationcoef2']; 984 $gi->weightoverride = $fromdefaults['weightoverride']; 985 986 $to = GRADE_AGGREGATE_SUM; 987 $todefaults = grade_category::get_default_aggregation_coefficient_values($to); 988 989 $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: $from, to: $to"); 990 $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); 991 $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); 992 $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); 993 } 994 995 /** 996 * Test that grade item event triggered when a grade item is created. 997 */ 998 protected function sub_test_grade_item_created_event() { 999 $sink = $this->redirectEvents(); 1000 1001 $gradeitem = new grade_item(); 1002 1003 $gradeitem->courseid = $this->courseid; 1004 $gradeitem->categoryid = $this->grade_categories[1]->id; 1005 $gradeitem->itemname = 'unittestgradeitem4'; 1006 $gradeitem->itemtype = 'mod'; 1007 $gradeitem->itemmodule = 'quiz'; 1008 $gradeitem->iteminfo = 'Grade item used for unit testing'; 1009 1010 $gradeitem->insert(); 1011 1012 $result = $sink->get_events(); 1013 $sink->close(); 1014 1015 $this->assertCount(1, $result); 1016 1017 $event = reset($result); 1018 $this->assertEventContextNotUsed($event); 1019 $this->assertInstanceOf('core\event\grade_item_created', $event); 1020 1021 $eventgradeitem = $event->get_grade_item(); 1022 1023 $this->assertInstanceOf('grade_item', $eventgradeitem); 1024 $this->assertEquals($gradeitem->id, $eventgradeitem->id); 1025 $this->assertEquals($gradeitem->itemname, $event->other['itemname']); 1026 $this->assertEquals($gradeitem->itemtype, $event->other['itemtype']); 1027 $this->assertEquals($gradeitem->itemmodule, $event->other['itemmodule']); 1028 } 1029 1030 /** 1031 * Test that grade item event triggered when a grade item is updated. 1032 */ 1033 protected function sub_test_grade_item_updated_event() { 1034 $gradeitem = new grade_item(); 1035 1036 $gradeitem->courseid = $this->courseid; 1037 $gradeitem->categoryid = $this->grade_categories[1]->id; 1038 $gradeitem->itemname = 'unittestgradeitem4'; 1039 $gradeitem->itemtype = 'mod'; 1040 $gradeitem->itemmodule = 'quiz'; 1041 $gradeitem->iteminfo = 'Grade item used for unit testing'; 1042 $gradeitem->insert(); 1043 1044 $sink = $this->redirectEvents(); 1045 1046 $gradeitem->itemname = 'updatedname'; 1047 $gradeitem->update(); 1048 1049 $result = $sink->get_events(); 1050 $sink->close(); 1051 1052 $this->assertCount(1, $result); 1053 1054 $event = reset($result); 1055 $this->assertInstanceOf('core\event\grade_item_updated', $event); 1056 $this->assertEventContextNotUsed($event); 1057 1058 $eventgradeitem = $event->get_grade_item(); 1059 1060 $this->assertInstanceOf('grade_item', $eventgradeitem); 1061 $this->assertEquals($gradeitem->id, $eventgradeitem->id); 1062 $this->assertEquals($gradeitem->itemtype, $event->other['itemtype']); 1063 $this->assertEquals($gradeitem->itemmodule, $event->other['itemmodule']); 1064 $this->assertEquals('updatedname', $event->other['itemname']); 1065 } 1066 1067 1068 /** 1069 * Test grade item duplication expecting success. 1070 */ 1071 public function test_grade_duplicate_grade_item_success() { 1072 $cat = new grade_category(); 1073 $cat->courseid = $this->courseid; 1074 $cat->fullname = 'Grade category'; 1075 $cat->insert(); 1076 1077 // Method exists. 1078 $gi = new grade_item(); 1079 $this->assertTrue(method_exists($gi, 'duplicate')); 1080 1081 // Grade item is inserted and valid for duplication. 1082 $gi->courseid = $this->courseid; 1083 $gi->categoryid = $cat->id; 1084 $gi->itemtype = 'manual'; 1085 $gi->itemname = 'Grade Item 1'; 1086 $gi->idnumber = '1000'; 1087 $gi->insert(); 1088 $gi2 = $gi->duplicate(); 1089 1090 $this->assertEquals($gi->courseid, $gi2->courseid); 1091 $this->assertEquals($gi->categoryid, $gi2->categoryid); 1092 $this->assertEquals($gi->itemtype, $gi2->itemtype); 1093 $this->assertEquals($gi->gradetype, $gi2->gradetype); 1094 $this->assertEquals($gi->grademax, $gi2->grademax); 1095 $this->assertEquals($gi->grademin, $gi2->grademin); 1096 $this->assertEquals($gi->gradepass, $gi2->gradepass); 1097 $this->assertEquals($gi->display, $gi2->display); 1098 $this->assertEquals($gi->decimals, $gi2->decimals); 1099 $this->assertEquals($gi->hidden, $gi2->hidden); 1100 $this->assertEquals($gi->weightoverride, $gi2->weightoverride); 1101 1102 $this->assertNotEquals($gi->id, $gi2->id); 1103 $this->assertNotEquals($gi->idnumber, $gi2->idnumber); 1104 $this->assertNotEquals($gi->sortorder, $gi2->sortorder); 1105 $this->assertNotEquals($gi->itemname, $gi2->itemname); 1106 } 1107 1108 /** 1109 * Test grade item duplication exception expected with incomplete grade item. 1110 */ 1111 public function test_grade_duplicate_grade_item_incomplete() { 1112 // Grade item is not valid because it is empty. 1113 $gi = new grade_item(); 1114 $gi->courseid = $this->courseid; 1115 $this->expectException("moodle_exception"); 1116 $gi2 = $gi->duplicate(); 1117 } 1118 1119 /** 1120 * Test grade item duplication exception expected because item must be in db. 1121 */ 1122 public function test_grade_duplicate_grade_item_not_in_db() { 1123 $cat = new grade_category(); 1124 $cat->courseid = $this->courseid; 1125 $cat->fullname = 'Grade category'; 1126 $cat->insert(); 1127 1128 // Grade item is valid for insertion but is not inserted into db. 1129 // Duplicate method throws an exception. 1130 $gi = new grade_item(); 1131 $gi->courseid = $this->courseid; 1132 $gi->categoryid = $cat->id; 1133 $gi->itemtype = 'manual'; 1134 $gi->itemname = 'Grade Item 1'; 1135 $gi->idnumber = '1000'; 1136 1137 $this->expectException("moodle_exception"); 1138 $gi2 = $gi->duplicate(); 1139 } 1140 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body