See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace gradereport_user; 18 19 use externallib_advanced_testcase; 20 use gradereport_user\external\user as user_external; 21 22 defined('MOODLE_INTERNAL') || die(); 23 24 global $CFG; 25 26 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 27 28 /** 29 * User grade report functions unit tests 30 * 31 * @package gradereport_user 32 * @category external 33 * @copyright 2015 Juan Leyva <juan@moodle.com> 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class externallib_test extends externallib_advanced_testcase { 37 38 /** 39 * Loads some data to be used by the different tests 40 * @param int $s1grade Student 1 grade 41 * @param int $s2grade Student 2 grade 42 * @return array Course and users instances 43 */ 44 private function load_data(int $s1grade, int $s2grade): array { 45 global $DB; 46 47 $course = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1]); 48 49 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 50 $student1 = $this->getDataGenerator()->create_user(['idnumber' => 'testidnumber']); 51 $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id); 52 53 $student2 = $this->getDataGenerator()->create_user(); 54 $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id); 55 56 $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']); 57 $teacher = $this->getDataGenerator()->create_user(); 58 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 59 60 $context = \context_course::instance($course->id); 61 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context); 62 accesslib_clear_all_caches_for_unit_testing(); 63 64 $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 65 $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 66 groups_add_member($group1->id, $student1->id); 67 groups_add_member($group1->id, $teacher->id); 68 groups_add_member($group2->id, $student2->id); 69 70 $assignment = $this->getDataGenerator()->create_module('assign', ['name' => "Test assign", 'course' => $course->id]); 71 $modcontext = get_coursemodule_from_instance('assign', $assignment->id, $course->id); 72 $assignment->cmidnumber = $modcontext->id; 73 74 $student1grade = ['userid' => $student1->id, 'rawgrade' => $s1grade, 'idnumber' => 'testidnumber1']; 75 $student2grade = ['userid' => $student2->id, 'rawgrade' => $s2grade, 'idnumber' => 'testidnumber2']; 76 $studentgrades = [$student1->id => $student1grade, $student2->id => $student2grade]; 77 assign_grade_item_update($assignment, $studentgrades); 78 79 return [ 80 $course, 81 $teacher, 82 $student1, 83 $student2, 84 $assignment 85 ]; 86 } 87 88 /** 89 * Test get_grades_table function case teacher 90 */ 91 public function test_get_grades_table_teacher() { 92 93 $this->resetAfterTest(true); 94 95 $s1grade = 80; 96 $s2grade = 60; 97 98 list($course, $teacher, $student1, $student2, $assignment) = $this->load_data($s1grade, $s2grade); 99 100 // A teacher must see all student grades (in their group only). 101 $this->setUser($teacher); 102 103 $studentgrades = user_external::get_grades_table($course->id); 104 $studentgrades = \external_api::clean_returnvalue(user_external::get_grades_table_returns(), $studentgrades); 105 106 // No warnings returned. 107 $this->assertCount(0, $studentgrades['warnings']); 108 109 // Check that only grades for the student in the teacher group are returned. 110 $this->assertCount(1, $studentgrades['tables']); 111 112 // Read returned grades. 113 $studentreturnedgrades = []; 114 115 $studentreturnedgrades[$studentgrades['tables'][0]['userid']] = 116 (int) $studentgrades['tables'][0]['tabledata'][2]['grade']['content']; 117 118 $this->assertEquals($s1grade, $studentreturnedgrades[$student1->id]); 119 } 120 121 /** 122 * Test get_grades_table function case student 123 */ 124 public function test_get_grades_table_student() { 125 global $CFG, $DB; 126 127 $this->resetAfterTest(true); 128 129 $s1grade = 80; 130 $s2grade = 60; 131 132 list($course, $teacher, $student1, $student2, $assignment) = $this->load_data($s1grade, $s2grade); 133 134 // A user can see his own grades. 135 $this->setUser($student1); 136 $studentgrade = user_external::get_grades_table($course->id, $student1->id); 137 $studentgrade = \external_api::clean_returnvalue(user_external::get_grades_table_returns(), $studentgrade); 138 139 // No warnings returned. 140 $this->assertTrue(count($studentgrade['warnings']) == 0); 141 142 $this->assertTrue(count($studentgrade['tables']) == 1); 143 $student1returnedgrade = (int) $studentgrade['tables'][0]['tabledata'][2]['grade']['content']; 144 $this->assertEquals($s1grade, $student1returnedgrade); 145 146 } 147 148 /** 149 * Test get_grades_table function case incorrect permissions 150 */ 151 public function test_get_grades_table_permissions() { 152 global $CFG, $DB; 153 154 $this->resetAfterTest(true); 155 156 $s1grade = 80; 157 $s2grade = 60; 158 159 list($course, $teacher, $student1, $student2, $assignment) = $this->load_data($s1grade, $s2grade); 160 161 $this->setUser($student2); 162 163 try { 164 $studentgrade = user_external::get_grades_table($course->id, $student1->id); 165 $this->fail('Exception expected due to not perissions to view other user grades.'); 166 } catch (\moodle_exception $e) { 167 $this->assertEquals('notingroup', $e->errorcode); 168 } 169 } 170 171 /** 172 * Test view_grade_report function 173 */ 174 public function test_view_grade_report() { 175 global $USER; 176 177 $this->resetAfterTest(true); 178 179 $s1grade = 80; 180 $s2grade = 60; 181 list($course, $teacher, $student1, $student2, $assignment) = $this->load_data($s1grade, $s2grade); 182 183 // Redirect events to the sink, so we can recover them later. 184 $sink = $this->redirectEvents(); 185 186 $this->setUser($student1); 187 $result = user_external::view_grade_report($course->id); 188 $result = \external_api::clean_returnvalue(user_external::view_grade_report_returns(), $result); 189 $events = $sink->get_events(); 190 $this->assertCount(1, $events); 191 $event = reset($events); 192 193 // Check the event details are correct. 194 $this->assertInstanceOf('\gradereport_user\event\grade_report_viewed', $event); 195 $this->assertEquals(\context_course::instance($course->id), $event->get_context()); 196 $this->assertEquals($USER->id, $event->get_data()['relateduserid']); 197 198 $this->setUser($teacher); 199 $result = user_external::view_grade_report($course->id, $student1->id); 200 $result = \external_api::clean_returnvalue(user_external::view_grade_report_returns(), $result); 201 $events = $sink->get_events(); 202 $event = reset($events); 203 $sink->close(); 204 205 // Check the event details are correct. 206 $this->assertInstanceOf('\gradereport_user\event\grade_report_viewed', $event); 207 $this->assertEquals(\context_course::instance($course->id), $event->get_context()); 208 $this->assertEquals($student1->id, $event->get_data()['relateduserid']); 209 210 $this->setUser($student2); 211 try { 212 $studentgrade = user_external::view_grade_report($course->id, $student1->id); 213 $this->fail('Exception expected due to not permissions to view other user grades.'); 214 } catch (\moodle_exception $e) { 215 $this->assertEquals('nopermissiontoviewgrades', $e->errorcode); 216 } 217 } 218 219 /** 220 * Test get_grades_items function case teacher 221 */ 222 public function test_get_grade_items_teacher() { 223 224 $this->resetAfterTest(true); 225 226 $s1grade = 80; 227 $s2grade = 60; 228 229 list($course, $teacher, $student1, $student2, $assignment) = $this->load_data($s1grade, $s2grade); 230 231 // A teacher must see all student grades (in their group only). 232 $this->setUser($teacher); 233 234 grade_set_setting($course->id, 'report_user_showrank', 1); 235 grade_set_setting($course->id, 'report_user_showpercentage', 1); 236 grade_set_setting($course->id, 'report_user_showhiddenitems', 1); 237 grade_set_setting($course->id, 'report_user_showgrade', 1); 238 grade_set_setting($course->id, 'report_user_showfeedback', 1); 239 grade_set_setting($course->id, 'report_user_showweight', 1); 240 grade_set_setting($course->id, 'report_user_showcontributiontocoursetotal', 1); 241 grade_set_setting($course->id, 'report_user_showlettergrade', 1); 242 grade_set_setting($course->id, 'report_user_showaverage', 1); 243 244 $studentgrades = user_external::get_grade_items($course->id); 245 $studentgrades = \external_api::clean_returnvalue(user_external::get_grade_items_returns(), $studentgrades); 246 // No warnings returned. 247 $this->assertCount(0, $studentgrades['warnings']); 248 249 // Check that only grades for the student in the teacher group are returned. 250 $this->assertCount(1, $studentgrades['usergrades']); 251 $this->assertCount(2, $studentgrades['usergrades'][0]['gradeitems']); 252 253 $this->assertEquals($course->id, $studentgrades['usergrades'][0]['courseid']); 254 $this->assertEquals($student1->id, $studentgrades['usergrades'][0]['userid']); 255 // Module grades. 256 $this->assertEquals($assignment->name, $studentgrades['usergrades'][0]['gradeitems'][0]['itemname']); 257 $this->assertEquals('mod', $studentgrades['usergrades'][0]['gradeitems'][0]['itemtype']); 258 $this->assertEquals('assign', $studentgrades['usergrades'][0]['gradeitems'][0]['itemmodule']); 259 $this->assertEquals($assignment->id, $studentgrades['usergrades'][0]['gradeitems'][0]['iteminstance']); 260 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['locked']); 261 $this->assertEquals($assignment->cmidnumber, $studentgrades['usergrades'][0]['gradeitems'][0]['cmid']); 262 $this->assertEquals(0, $studentgrades['usergrades'][0]['gradeitems'][0]['itemnumber']); 263 $this->assertEmpty($studentgrades['usergrades'][0]['gradeitems'][0]['outcomeid']); 264 $this->assertEmpty($studentgrades['usergrades'][0]['gradeitems'][0]['scaleid']); 265 $this->assertEquals(80, $studentgrades['usergrades'][0]['gradeitems'][0]['graderaw']); 266 $this->assertEquals('80.00', $studentgrades['usergrades'][0]['gradeitems'][0]['gradeformatted']); 267 $this->assertEquals(0, $studentgrades['usergrades'][0]['gradeitems'][0]['grademin']); 268 $this->assertEquals(100, $studentgrades['usergrades'][0]['gradeitems'][0]['grademax']); 269 $this->assertEquals('0–100', $studentgrades['usergrades'][0]['gradeitems'][0]['rangeformatted']); 270 $this->assertEquals('80.00 %', $studentgrades['usergrades'][0]['gradeitems'][0]['percentageformatted']); 271 $this->assertEmpty($studentgrades['usergrades'][0]['gradeitems'][0]['feedback']); 272 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['gradehiddenbydate']); 273 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['gradeneedsupdate']); 274 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['gradeishidden']); 275 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['gradeislocked']); 276 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['gradeisoverridden']); 277 $this->assertEquals('B-', $studentgrades['usergrades'][0]['gradeitems'][0]['lettergradeformatted']); 278 $this->assertEquals(1, $studentgrades['usergrades'][0]['gradeitems'][0]['rank']); 279 $this->assertEquals(2, $studentgrades['usergrades'][0]['gradeitems'][0]['numusers']); 280 $this->assertEquals(70, $studentgrades['usergrades'][0]['gradeitems'][0]['averageformatted']); 281 282 // Course grades. 283 $this->assertEquals('course', $studentgrades['usergrades'][0]['gradeitems'][1]['itemtype']); 284 $this->assertEquals(80, $studentgrades['usergrades'][0]['gradeitems'][1]['graderaw']); 285 $this->assertEquals('80.00', $studentgrades['usergrades'][0]['gradeitems'][1]['gradeformatted']); 286 $this->assertEquals(0, $studentgrades['usergrades'][0]['gradeitems'][1]['grademin']); 287 $this->assertEquals(100, $studentgrades['usergrades'][0]['gradeitems'][1]['grademax']); 288 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][1]['locked']); 289 $this->assertEquals('0–100', $studentgrades['usergrades'][0]['gradeitems'][1]['rangeformatted']); 290 $this->assertEquals('80.00 %', $studentgrades['usergrades'][0]['gradeitems'][1]['percentageformatted']); 291 $this->assertEmpty($studentgrades['usergrades'][0]['gradeitems'][1]['feedback']); 292 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][1]['gradehiddenbydate']); 293 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][1]['gradeneedsupdate']); 294 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][1]['gradeishidden']); 295 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][1]['gradeislocked']); 296 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][1]['gradeisoverridden']); 297 $this->assertEquals('B-', $studentgrades['usergrades'][0]['gradeitems'][1]['lettergradeformatted']); 298 $this->assertEquals(1, $studentgrades['usergrades'][0]['gradeitems'][1]['rank']); 299 $this->assertEquals(2, $studentgrades['usergrades'][0]['gradeitems'][1]['numusers']); 300 $this->assertEquals(70, $studentgrades['usergrades'][0]['gradeitems'][1]['averageformatted']); 301 302 // Now, override and lock a grade. 303 $gradegrade = \grade_grade::fetch(['itemid' => $studentgrades['usergrades'][0]['gradeitems'][0]['id'], 304 'userid' => $studentgrades['usergrades'][0]['userid']]); 305 $gradegrade->set_overridden(true); 306 $gradegrade->set_locked(1); 307 308 $studentgrades = user_external::get_grade_items($course->id); 309 $studentgrades = \external_api::clean_returnvalue(user_external::get_grade_items_returns(), $studentgrades); 310 // No warnings returned. 311 $this->assertCount(0, $studentgrades['warnings']); 312 313 // Module grades. 314 $this->assertTrue($studentgrades['usergrades'][0]['gradeitems'][0]['gradeislocked']); 315 $this->assertTrue($studentgrades['usergrades'][0]['gradeitems'][0]['gradeisoverridden']); 316 } 317 318 /** 319 * Test get_grades_items function case student 320 */ 321 public function test_get_grade_items_student() { 322 323 $this->resetAfterTest(true); 324 325 $s1grade = 80; 326 $s2grade = 60; 327 328 list($course, $teacher, $student1, $student2, $assignment) = $this->load_data($s1grade, $s2grade); 329 330 grade_set_setting($course->id, 'report_user_showrank', 1); 331 grade_set_setting($course->id, 'report_user_showpercentage', 1); 332 grade_set_setting($course->id, 'report_user_showgrade', 1); 333 grade_set_setting($course->id, 'report_user_showfeedback', 1); 334 grade_set_setting($course->id, 'report_user_showweight', 1); 335 grade_set_setting($course->id, 'report_user_showcontributiontocoursetotal', 1); 336 grade_set_setting($course->id, 'report_user_showlettergrade', 1); 337 grade_set_setting($course->id, 'report_user_showaverage', 1); 338 339 $this->setUser($student1); 340 341 $studentgrades = user_external::get_grade_items($course->id, $student1->id); 342 $studentgrades = \external_api::clean_returnvalue(user_external::get_grade_items_returns(), $studentgrades); 343 // No warnings returned. 344 $this->assertCount(0, $studentgrades['warnings']); 345 346 // Check that only grades for the student in the teacher group are returned. 347 $this->assertCount(1, $studentgrades['usergrades']); 348 $this->assertCount(2, $studentgrades['usergrades'][0]['gradeitems']); 349 350 $this->assertEquals($course->id, $studentgrades['usergrades'][0]['courseid']); 351 $this->assertEquals($student1->id, $studentgrades['usergrades'][0]['userid']); 352 $this->assertEquals($student1->idnumber, $studentgrades['usergrades'][0]['useridnumber']); 353 $this->assertEquals($assignment->name, $studentgrades['usergrades'][0]['gradeitems'][0]['itemname']); 354 $this->assertEquals('mod', $studentgrades['usergrades'][0]['gradeitems'][0]['itemtype']); 355 $this->assertEquals('assign', $studentgrades['usergrades'][0]['gradeitems'][0]['itemmodule']); 356 $this->assertEquals($assignment->id, $studentgrades['usergrades'][0]['gradeitems'][0]['iteminstance']); 357 $this->assertNull($studentgrades['usergrades'][0]['gradeitems'][0]['locked']); 358 $this->assertEquals($assignment->cmidnumber, $studentgrades['usergrades'][0]['gradeitems'][0]['cmid']); 359 $this->assertEquals(0, $studentgrades['usergrades'][0]['gradeitems'][0]['itemnumber']); 360 $this->assertEmpty($studentgrades['usergrades'][0]['gradeitems'][0]['outcomeid']); 361 $this->assertEmpty($studentgrades['usergrades'][0]['gradeitems'][0]['scaleid']); 362 $this->assertEquals(80, $studentgrades['usergrades'][0]['gradeitems'][0]['graderaw']); 363 $this->assertEquals('80.00', $studentgrades['usergrades'][0]['gradeitems'][0]['gradeformatted']); 364 $this->assertEquals(0, $studentgrades['usergrades'][0]['gradeitems'][0]['grademin']); 365 $this->assertEquals(100, $studentgrades['usergrades'][0]['gradeitems'][0]['grademax']); 366 $this->assertEquals('0–100', $studentgrades['usergrades'][0]['gradeitems'][0]['rangeformatted']); 367 $this->assertEquals('80.00 %', $studentgrades['usergrades'][0]['gradeitems'][0]['percentageformatted']); 368 $this->assertEmpty($studentgrades['usergrades'][0]['gradeitems'][0]['feedback']); 369 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['gradehiddenbydate']); 370 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['gradeneedsupdate']); 371 $this->assertFalse($studentgrades['usergrades'][0]['gradeitems'][0]['gradeishidden']); 372 $this->assertNull($studentgrades['usergrades'][0]['gradeitems'][0]['gradeislocked']); 373 $this->assertNull($studentgrades['usergrades'][0]['gradeitems'][0]['gradeisoverridden']); 374 $this->assertEquals('B-', $studentgrades['usergrades'][0]['gradeitems'][0]['lettergradeformatted']); 375 $this->assertEquals(1, $studentgrades['usergrades'][0]['gradeitems'][0]['rank']); 376 $this->assertEquals(2, $studentgrades['usergrades'][0]['gradeitems'][0]['numusers']); 377 $this->assertEquals(70, $studentgrades['usergrades'][0]['gradeitems'][0]['averageformatted']); 378 379 // Check that the idnumber for assignment grades is equal to the cmid. 380 $this->assertEquals((string) $studentgrades['usergrades'][0]['gradeitems'][0]['cmid'], 381 $studentgrades['usergrades'][0]['gradeitems'][0]['idnumber']); 382 383 // Hide one grade for the user. 384 $gradegrade = new \grade_grade([ 385 'userid' => $student1->id, 386 'itemid' => $studentgrades['usergrades'][0]['gradeitems'][0]['id'] 387 ], true); 388 $gradegrade->set_hidden(1); 389 $studentgrades = user_external::get_grade_items($course->id, $student1->id); 390 $studentgrades = \external_api::clean_returnvalue(user_external::get_grade_items_returns(), $studentgrades); 391 392 // Check we get only the course final grade. 393 $this->assertCount(1, $studentgrades['usergrades']); 394 $this->assertCount(1, $studentgrades['usergrades'][0]['gradeitems']); 395 $this->assertEquals('course', $studentgrades['usergrades'][0]['gradeitems'][0]['itemtype']); 396 } 397 398 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body