PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/grade/tests/grade_item_test.php

https://bitbucket.org/moodle/moodle
PHP | 1140 lines | 794 code | 222 blank | 124 comment | 26 complexity | 6d8c5350f5dc793eb41eb0c676774c6a MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file