Differences Between: [Versions 311 and 402] [Versions 400 and 402] [Versions 401 and 402]
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 * Workshop module external functions tests 19 * 20 * @package mod_workshop 21 * @category external 22 * @copyright 2017 Juan Leyva <juan@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 * @since Moodle 3.4 25 */ 26 27 namespace mod_workshop\external; 28 29 use core_external\external_api; 30 use externallib_advanced_testcase; 31 use mod_workshop_external; 32 use workshop; 33 34 defined('MOODLE_INTERNAL') || die(); 35 36 global $CFG; 37 38 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 39 require_once($CFG->dirroot . '/mod/workshop/lib.php'); 40 41 /** 42 * Workshop module external functions tests 43 * 44 * @package mod_workshop 45 * @category external 46 * @copyright 2017 Juan Leyva <juan@moodle.com> 47 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 48 * @since Moodle 3.4 49 */ 50 class external_test extends externallib_advanced_testcase { 51 52 /** @var stdClass course object */ 53 private $course; 54 /** @var stdClass workshop object */ 55 private $workshop; 56 /** @var stdClass context object */ 57 private $context; 58 /** @var stdClass cm object */ 59 private $cm; 60 /** @var stdClass student object */ 61 private $student; 62 /** @var stdClass teacher object */ 63 private $teacher; 64 /** @var stdClass student role object */ 65 private $studentrole; 66 /** @var stdClass teacher role object */ 67 private $teacherrole; 68 /** @var \stdClass student object. */ 69 private $anotherstudentg1; 70 /** @var \stdClass student object. */ 71 private $anotherstudentg2; 72 /** @var \stdClass group object. */ 73 private $group1; 74 /** @var \stdClass group object. */ 75 private $group2; 76 77 /** 78 * Set up for every test 79 */ 80 public function setUp(): void { 81 global $DB; 82 $this->resetAfterTest(); 83 $this->setAdminUser(); 84 85 // Setup test data. 86 $course = new \stdClass(); 87 $course->groupmode = SEPARATEGROUPS; 88 $course->groupmodeforce = true; 89 $this->course = $this->getDataGenerator()->create_course($course); 90 $this->workshop = $this->getDataGenerator()->create_module('workshop', 91 array( 92 'course' => $this->course->id, 93 'overallfeedbackfiles' => 1, 94 ) 95 ); 96 $this->context = \context_module::instance($this->workshop->cmid); 97 $this->cm = get_coursemodule_from_instance('workshop', $this->workshop->id); 98 99 // Add grading strategy data (accumulative is the default). 100 $workshop = new workshop($this->workshop, $this->cm, $this->course); 101 $strategy = $workshop->grading_strategy_instance(); 102 $data = array(); 103 for ($i = 0; $i < 4; $i++) { 104 $data['dimensionid__idx_'.$i] = 0; 105 $data['description__idx_'.$i.'_editor'] = array('text' => "Content $i", 'format' => FORMAT_MOODLE); 106 $data['grade__idx_'.$i] = 25; 107 $data['weight__idx_'.$i] = 25; 108 } 109 $data['workshopid'] = $workshop->id; 110 $data['norepeats'] = 4; 111 $strategy->save_edit_strategy_form((object) $data); 112 113 // Create users. 114 $this->student = self::getDataGenerator()->create_user(); 115 $this->anotherstudentg1 = self::getDataGenerator()->create_user(); 116 $this->anotherstudentg2 = self::getDataGenerator()->create_user(); 117 $this->teacher = self::getDataGenerator()->create_user(); 118 119 // Users enrolments. 120 $this->studentrole = $DB->get_record('role', array('shortname' => 'student')); 121 $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 122 $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual'); 123 $this->getDataGenerator()->enrol_user($this->anotherstudentg1->id, $this->course->id, $this->studentrole->id, 'manual'); 124 $this->getDataGenerator()->enrol_user($this->anotherstudentg2->id, $this->course->id, $this->studentrole->id, 'manual'); 125 $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual'); 126 127 $this->group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id)); 128 $this->group2 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id)); 129 groups_add_member($this->group1, $this->student); 130 groups_add_member($this->group1, $this->anotherstudentg1); 131 groups_add_member($this->group2, $this->anotherstudentg2); 132 } 133 134 /** 135 * Test test_mod_workshop_get_workshops_by_courses 136 */ 137 public function test_mod_workshop_get_workshops_by_courses() { 138 139 // Create additional course. 140 $course2 = self::getDataGenerator()->create_course(); 141 142 // Second workshop. 143 $record = new \stdClass(); 144 $record->course = $course2->id; 145 $workshop2 = self::getDataGenerator()->create_module('workshop', $record); 146 147 // Execute real Moodle enrolment as we'll call unenrol() method on the instance later. 148 $enrol = enrol_get_plugin('manual'); 149 $enrolinstances = enrol_get_instances($course2->id, true); 150 foreach ($enrolinstances as $courseenrolinstance) { 151 if ($courseenrolinstance->enrol == "manual") { 152 $instance2 = $courseenrolinstance; 153 break; 154 } 155 } 156 $enrol->enrol_user($instance2, $this->student->id, $this->studentrole->id); 157 158 self::setUser($this->student); 159 160 $returndescription = mod_workshop_external::get_workshops_by_courses_returns(); 161 162 // Create what we expect to be returned when querying the two courses. 163 $properties = workshop_summary_exporter::read_properties_definition(); 164 $expectedfields = array_keys($properties); 165 166 // Add expected coursemodule and data. 167 $workshop1 = $this->workshop; 168 $workshop1->coursemodule = $workshop1->cmid; 169 $workshop1->introformat = 1; 170 $workshop1->introfiles = []; 171 $workshop1->lang = ''; 172 $workshop1->instructauthorsfiles = []; 173 $workshop1->instructauthorsformat = 1; 174 $workshop1->instructreviewersfiles = []; 175 $workshop1->instructreviewersformat = 1; 176 $workshop1->conclusionfiles = []; 177 $workshop1->conclusionformat = 1; 178 $workshop1->submissiontypetext = 1; 179 $workshop1->submissiontypefile = 1; 180 181 $workshop2->coursemodule = $workshop2->cmid; 182 $workshop2->introformat = 1; 183 $workshop2->introfiles = []; 184 $workshop2->lang = ''; 185 $workshop2->instructauthorsfiles = []; 186 $workshop2->instructauthorsformat = 1; 187 $workshop2->instructreviewersfiles = []; 188 $workshop2->instructreviewersformat = 1; 189 $workshop2->conclusionfiles = []; 190 $workshop2->conclusionformat = 1; 191 $workshop2->submissiontypetext = 1; 192 $workshop2->submissiontypefile = 1; 193 194 foreach ($expectedfields as $field) { 195 if (!empty($properties[$field]) && $properties[$field]['type'] == PARAM_BOOL) { 196 $workshop1->{$field} = (bool) $workshop1->{$field}; 197 $workshop2->{$field} = (bool) $workshop2->{$field}; 198 } 199 $expected1[$field] = $workshop1->{$field}; 200 $expected2[$field] = $workshop2->{$field}; 201 } 202 203 $expectedworkshops = array($expected2, $expected1); 204 205 // Call the external function passing course ids. 206 $result = mod_workshop_external::get_workshops_by_courses(array($course2->id, $this->course->id)); 207 $result = external_api::clean_returnvalue($returndescription, $result); 208 209 $this->assertEquals($expectedworkshops, $result['workshops']); 210 $this->assertCount(0, $result['warnings']); 211 212 // Call the external function without passing course id. 213 $result = mod_workshop_external::get_workshops_by_courses(); 214 $result = external_api::clean_returnvalue($returndescription, $result); 215 $this->assertEquals($expectedworkshops, $result['workshops']); 216 $this->assertCount(0, $result['warnings']); 217 218 // Unenrol user from second course and alter expected workshops. 219 $enrol->unenrol_user($instance2, $this->student->id); 220 array_shift($expectedworkshops); 221 222 // Call the external function without passing course id. 223 $result = mod_workshop_external::get_workshops_by_courses(); 224 $result = external_api::clean_returnvalue($returndescription, $result); 225 $this->assertEquals($expectedworkshops, $result['workshops']); 226 227 // Call for the second course we unenrolled the user from, expected warning. 228 $result = mod_workshop_external::get_workshops_by_courses(array($course2->id)); 229 $this->assertCount(1, $result['warnings']); 230 $this->assertEquals('1', $result['warnings'][0]['warningcode']); 231 $this->assertEquals($course2->id, $result['warnings'][0]['itemid']); 232 } 233 234 /** 235 * Test mod_workshop_get_workshop_access_information for students. 236 */ 237 public function test_mod_workshop_get_workshop_access_information_student() { 238 239 self::setUser($this->student); 240 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 241 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 242 // Check default values for capabilities. 243 $enabledcaps = array('canpeerassess', 'cansubmit', 'canview', 'canviewauthornames', 'canviewauthorpublished', 244 'canviewpublishedsubmissions', 'canexportsubmissions'); 245 246 foreach ($result as $capname => $capvalue) { 247 if (strpos($capname, 'can') !== 0) { 248 continue; 249 } 250 if (in_array($capname, $enabledcaps)) { 251 $this->assertTrue($capvalue); 252 } else { 253 $this->assertFalse($capvalue); 254 } 255 } 256 // Now, unassign some capabilities. 257 unassign_capability('mod/workshop:peerassess', $this->studentrole->id); 258 unassign_capability('mod/workshop:submit', $this->studentrole->id); 259 unset($enabledcaps[0]); 260 unset($enabledcaps[1]); 261 accesslib_clear_all_caches_for_unit_testing(); 262 263 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 264 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 265 foreach ($result as $capname => $capvalue) { 266 if (strpos($capname, 'can') !== 0) { 267 continue; 268 } 269 if (in_array($capname, $enabledcaps)) { 270 $this->assertTrue($capvalue); 271 } else { 272 $this->assertFalse($capvalue); 273 } 274 } 275 276 // Now, specific functionalities. 277 $this->assertFalse($result['creatingsubmissionallowed']); 278 $this->assertFalse($result['modifyingsubmissionallowed']); 279 $this->assertFalse($result['assessingallowed']); 280 $this->assertFalse($result['assessingexamplesallowed']); 281 $this->assertTrue($result['examplesassessedbeforesubmission']); 282 $this->assertTrue($result['examplesassessedbeforeassessment']); 283 284 // Switch phase. 285 $workshop = new workshop($this->workshop, $this->cm, $this->course); 286 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 287 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 288 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 289 290 $this->assertTrue($result['creatingsubmissionallowed']); 291 $this->assertTrue($result['modifyingsubmissionallowed']); 292 $this->assertFalse($result['assessingallowed']); 293 $this->assertFalse($result['assessingexamplesallowed']); 294 $this->assertTrue($result['examplesassessedbeforesubmission']); 295 $this->assertTrue($result['examplesassessedbeforeassessment']); 296 297 // Switch to next (to assessment). 298 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 299 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 300 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 301 302 $this->assertFalse($result['creatingsubmissionallowed']); 303 $this->assertFalse($result['modifyingsubmissionallowed']); 304 $this->assertTrue($result['assessingallowed']); 305 $this->assertFalse($result['assessingexamplesallowed']); 306 $this->assertTrue($result['examplesassessedbeforesubmission']); 307 $this->assertTrue($result['examplesassessedbeforeassessment']); 308 } 309 310 /** 311 * Test mod_workshop_get_workshop_access_information for teachers. 312 */ 313 public function test_mod_workshop_get_workshop_access_information_teacher() { 314 315 self::setUser($this->teacher); 316 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 317 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 318 // Check default values. 319 $disabledcaps = array('canpeerassess', 'cansubmit'); 320 321 foreach ($result as $capname => $capvalue) { 322 if (strpos($capname, 'can') !== 0) { 323 continue; 324 } 325 if (in_array($capname, $disabledcaps)) { 326 $this->assertFalse($capvalue); 327 } else { 328 $this->assertTrue($capvalue); 329 } 330 } 331 332 // Now, specific functionalities. 333 $this->assertFalse($result['creatingsubmissionallowed']); 334 $this->assertFalse($result['modifyingsubmissionallowed']); 335 $this->assertFalse($result['assessingallowed']); 336 $this->assertFalse($result['assessingexamplesallowed']); 337 } 338 339 /** 340 * Test mod_workshop_get_user_plan for students. 341 */ 342 public function test_mod_workshop_get_user_plan_student() { 343 344 self::setUser($this->student); 345 $result = mod_workshop_external::get_user_plan($this->workshop->id); 346 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 347 348 $this->assertCount(0, $result['userplan']['examples']); // No examples given. 349 $this->assertCount(5, $result['userplan']['phases']); // Always 5 phases. 350 $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']); // First phase always setup. 351 $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops. 352 353 // Switch phase. 354 $workshop = new workshop($this->workshop, $this->cm, $this->course); 355 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 356 357 $result = mod_workshop_external::get_user_plan($this->workshop->id); 358 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 359 360 $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']); 361 $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase. 362 } 363 364 /** 365 * Test mod_workshop_get_user_plan for teachers. 366 */ 367 public function test_mod_workshop_get_user_plan_teacher() { 368 369 self::setUser($this->teacher); 370 $result = mod_workshop_external::get_user_plan($this->workshop->id); 371 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 372 373 $this->assertCount(0, $result['userplan']['examples']); // No examples given. 374 $this->assertCount(5, $result['userplan']['phases']); // Always 5 phases. 375 $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']); // First phase always setup. 376 $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops. 377 $this->assertCount(4, $result['userplan']['phases'][0]['tasks']); // For new empty workshops, always 4 tasks. 378 379 foreach ($result['userplan']['phases'][0]['tasks'] as $task) { 380 if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform') { 381 $this->assertEquals(1, $task['completed']); 382 } else { 383 $this->assertEmpty($task['completed']); 384 } 385 } 386 387 // Do some of the tasks asked - switch phase. 388 $workshop = new workshop($this->workshop, $this->cm, $this->course); 389 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 390 391 $result = mod_workshop_external::get_user_plan($this->workshop->id); 392 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 393 foreach ($result['userplan']['phases'][0]['tasks'] as $task) { 394 if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform' || 395 $task['code'] == 'switchtonextphase') { 396 $this->assertEquals(1, $task['completed']); 397 } else { 398 $this->assertEmpty($task['completed']); 399 } 400 } 401 402 $result = mod_workshop_external::get_user_plan($this->workshop->id); 403 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 404 405 $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']); 406 $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase. 407 } 408 409 /** 410 * Test test_view_workshop invalid id. 411 */ 412 public function test_view_workshop_invalid_id() { 413 $this->expectException('moodle_exception'); 414 mod_workshop_external::view_workshop(0); 415 } 416 417 /** 418 * Test test_view_workshop user not enrolled. 419 */ 420 public function test_view_workshop_user_not_enrolled() { 421 // Test not-enrolled user. 422 $usernotenrolled = self::getDataGenerator()->create_user(); 423 $this->setUser($usernotenrolled); 424 $this->expectException('moodle_exception'); 425 mod_workshop_external::view_workshop($this->workshop->id); 426 } 427 428 /** 429 * Test test_view_workshop user student. 430 */ 431 public function test_view_workshop_user_student() { 432 // Test user with full capabilities. 433 $this->setUser($this->student); 434 435 // Trigger and capture the event. 436 $sink = $this->redirectEvents(); 437 438 $result = mod_workshop_external::view_workshop($this->workshop->id); 439 $result = external_api::clean_returnvalue(mod_workshop_external::view_workshop_returns(), $result); 440 $this->assertTrue($result['status']); 441 442 $events = $sink->get_events(); 443 $this->assertCount(1, $events); 444 $event = array_shift($events); 445 446 // Checking that the event contains the expected values. 447 $this->assertInstanceOf('\mod_workshop\event\course_module_viewed', $event); 448 $this->assertEquals($this->context, $event->get_context()); 449 $moodleworkshop = new \moodle_url('/mod/workshop/view.php', array('id' => $this->cm->id)); 450 $this->assertEquals($moodleworkshop, $event->get_url()); 451 $this->assertEventContextNotUsed($event); 452 $this->assertNotEmpty($event->get_name()); 453 } 454 455 /** 456 * Test test_view_workshop user missing capabilities. 457 */ 458 public function test_view_workshop_user_missing_capabilities() { 459 // Test user with no capabilities. 460 // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. 461 assign_capability('mod/workshop:view', CAP_PROHIBIT, $this->studentrole->id, $this->context->id); 462 // Empty all the caches that may be affected by this change. 463 accesslib_clear_all_caches_for_unit_testing(); 464 \course_modinfo::clear_instance_cache(); 465 466 $this->setUser($this->student); 467 $this->expectException('moodle_exception'); 468 mod_workshop_external::view_workshop($this->workshop->id); 469 } 470 471 /** 472 * Test test_add_submission. 473 */ 474 public function test_add_submission() { 475 $fs = get_file_storage(); 476 477 // Test user with full capabilities. 478 $this->setUser($this->student); 479 480 $title = 'Submission title'; 481 $content = 'Submission contents'; 482 483 // Create a file in a draft area for inline attachments. 484 $draftidinlineattach = file_get_unused_draft_itemid(); 485 $usercontext = \context_user::instance($this->student->id); 486 $filenameimg = 'shouldbeanimage.txt'; 487 $filerecordinline = array( 488 'contextid' => $usercontext->id, 489 'component' => 'user', 490 'filearea' => 'draft', 491 'itemid' => $draftidinlineattach, 492 'filepath' => '/', 493 'filename' => $filenameimg, 494 ); 495 $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); 496 497 // Create a file in a draft area for regular attachments. 498 $draftidattach = file_get_unused_draft_itemid(); 499 $filerecordattach = $filerecordinline; 500 $attachfilename = 'attachment.txt'; 501 $filerecordattach['filename'] = $attachfilename; 502 $filerecordattach['itemid'] = $draftidattach; 503 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 504 505 // Switch to submission phase. 506 $workshop = new workshop($this->workshop, $this->cm, $this->course); 507 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 508 509 $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach, 510 $draftidattach); 511 $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); 512 $this->assertEmpty($result['warnings']); 513 514 // Check submission created. 515 $submission = $workshop->get_submission_by_author($this->student->id); 516 $this->assertTrue($result['status']); 517 $this->assertEquals($result['submissionid'], $submission->id); 518 $this->assertEquals($title, $submission->title); 519 $this->assertEquals($content, $submission->content); 520 521 // Check files. 522 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id); 523 $this->assertCount(2, $contentfiles); 524 foreach ($contentfiles as $file) { 525 if ($file->is_directory()) { 526 continue; 527 } else { 528 $this->assertEquals($filenameimg, $file->get_filename()); 529 } 530 } 531 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id); 532 $this->assertCount(2, $contentfiles); 533 foreach ($contentfiles as $file) { 534 if ($file->is_directory()) { 535 continue; 536 } else { 537 $this->assertEquals($attachfilename, $file->get_filename()); 538 } 539 } 540 } 541 542 /** 543 * Test test_add_submission invalid phase. 544 */ 545 public function test_add_submission_invalid_phase() { 546 $this->setUser($this->student); 547 548 $this->expectException('moodle_exception'); 549 mod_workshop_external::add_submission($this->workshop->id, 'Test'); 550 } 551 552 /** 553 * Test test_add_submission empty title. 554 */ 555 public function test_add_submission_empty_title() { 556 $this->setUser($this->student); 557 558 // Switch to submission phase. 559 $workshop = new workshop($this->workshop, $this->cm, $this->course); 560 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 561 562 $this->expectException('moodle_exception'); 563 mod_workshop_external::add_submission($this->workshop->id, ''); 564 } 565 566 /** 567 * Test test_add_submission already added. 568 */ 569 public function test_add_submission_already_added() { 570 $this->setUser($this->student); 571 572 $usercontext = \context_user::instance($this->student->id); 573 $fs = get_file_storage(); 574 $draftidattach = file_get_unused_draft_itemid(); 575 $filerecordattach = [ 576 'contextid' => $usercontext->id, 577 'component' => 'user', 578 'filearea' => 'draft', 579 'itemid' => $draftidattach, 580 'filepath' => '/', 581 'filename' => 'attachement.txt' 582 ]; 583 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 584 585 // Switch to submission phase. 586 $workshop = new workshop($this->workshop, $this->cm, $this->course); 587 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 588 589 // Create the submission. 590 $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission', '', FORMAT_MOODLE, 0, $draftidattach); 591 $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); 592 593 // Try to create it again. 594 $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission', '', FORMAT_MOODLE, 0, $draftidattach); 595 $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); 596 $this->assertFalse($result['status']); 597 $this->assertArrayNotHasKey('submissionid', $result); 598 $this->assertCount(1, $result['warnings']); 599 $this->assertEquals('fielderror', $result['warnings'][0]['warningcode']); 600 $this->assertEquals('title', $result['warnings'][0]['item']); 601 } 602 603 /** 604 * Helper method to create a submission for testing for the given user. 605 * 606 * @param int $user the submission will be created by this student. 607 * @return int the submission id 608 */ 609 protected function create_test_submission($user) { 610 // Test user with full capabilities. 611 $this->setUser($user); 612 613 $title = 'Submission title'; 614 $content = 'Submission contents'; 615 616 // Create a file in a draft area for inline attachments. 617 $fs = get_file_storage(); 618 $draftidinlineattach = file_get_unused_draft_itemid(); 619 $usercontext = \context_user::instance($user->id); 620 $filenameimg = 'shouldbeanimage.txt'; 621 $filerecordinline = array( 622 'contextid' => $usercontext->id, 623 'component' => 'user', 624 'filearea' => 'draft', 625 'itemid' => $draftidinlineattach, 626 'filepath' => '/', 627 'filename' => $filenameimg, 628 ); 629 $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); 630 631 // Create a file in a draft area for regular attachments. 632 $draftidattach = file_get_unused_draft_itemid(); 633 $filerecordattach = $filerecordinline; 634 $attachfilename = 'attachment.txt'; 635 $filerecordattach['filename'] = $attachfilename; 636 $filerecordattach['itemid'] = $draftidattach; 637 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 638 639 // Switch to submission phase. 640 $workshop = new workshop($this->workshop, $this->cm, $this->course); 641 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 642 643 $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach, 644 $draftidattach); 645 return $result['submissionid']; 646 } 647 648 /** 649 * Test test_update_submission. 650 */ 651 public function test_update_submission() { 652 653 // Create the submission that will be updated. 654 $submissionid = $this->create_test_submission($this->student); 655 656 // Test user with full capabilities. 657 $this->setUser($this->student); 658 659 $title = 'Submission new title'; 660 $content = 'Submission new contents'; 661 662 // Create a different file in a draft area for inline attachments. 663 $fs = get_file_storage(); 664 $draftidinlineattach = file_get_unused_draft_itemid(); 665 $usercontext = \context_user::instance($this->student->id); 666 $filenameimg = 'shouldbeanimage_new.txt'; 667 $filerecordinline = array( 668 'contextid' => $usercontext->id, 669 'component' => 'user', 670 'filearea' => 'draft', 671 'itemid' => $draftidinlineattach, 672 'filepath' => '/', 673 'filename' => $filenameimg, 674 ); 675 $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); 676 677 // Create a different file in a draft area for regular attachments. 678 $draftidattach = file_get_unused_draft_itemid(); 679 $filerecordattach = $filerecordinline; 680 $attachfilename = 'attachment_new.txt'; 681 $filerecordattach['filename'] = $attachfilename; 682 $filerecordattach['itemid'] = $draftidattach; 683 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 684 685 $result = mod_workshop_external::update_submission($submissionid, $title, $content, FORMAT_MOODLE, $draftidinlineattach, 686 $draftidattach); 687 $result = external_api::clean_returnvalue(mod_workshop_external::update_submission_returns(), $result); 688 $this->assertEmpty($result['warnings']); 689 690 // Check submission updated. 691 $workshop = new workshop($this->workshop, $this->cm, $this->course); 692 $submission = $workshop->get_submission_by_id($submissionid); 693 $this->assertTrue($result['status']); 694 $this->assertEquals($title, $submission->title); 695 $this->assertEquals($content, $submission->content); 696 697 // Check files. 698 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id); 699 $this->assertCount(2, $contentfiles); 700 foreach ($contentfiles as $file) { 701 if ($file->is_directory()) { 702 continue; 703 } else { 704 $this->assertEquals($filenameimg, $file->get_filename()); 705 } 706 } 707 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id); 708 $this->assertCount(2, $contentfiles); 709 foreach ($contentfiles as $file) { 710 if ($file->is_directory()) { 711 continue; 712 } else { 713 $this->assertEquals($attachfilename, $file->get_filename()); 714 } 715 } 716 } 717 718 /** 719 * Test test_update_submission belonging to other user. 720 */ 721 public function test_update_submission_of_other_user() { 722 // Create the submission that will be updated. 723 $submissionid = $this->create_test_submission($this->student); 724 725 $this->setUser($this->teacher); 726 727 $this->expectException('moodle_exception'); 728 mod_workshop_external::update_submission($submissionid, 'Test'); 729 } 730 731 /** 732 * Test test_update_submission invalid phase. 733 */ 734 public function test_update_submission_invalid_phase() { 735 // Create the submission that will be updated. 736 $submissionid = $this->create_test_submission($this->student); 737 738 $this->setUser($this->student); 739 740 // Switch to assessment phase. 741 $workshop = new workshop($this->workshop, $this->cm, $this->course); 742 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 743 744 $this->expectException('moodle_exception'); 745 mod_workshop_external::update_submission($submissionid, 'Test'); 746 } 747 748 /** 749 * Test test_update_submission empty title. 750 */ 751 public function test_update_submission_empty_title() { 752 // Create the submission that will be updated. 753 $submissionid = $this->create_test_submission($this->student); 754 755 $this->setUser($this->student); 756 757 $this->expectException('moodle_exception'); 758 mod_workshop_external::update_submission($submissionid, ''); 759 } 760 761 /** 762 * Test test_delete_submission. 763 */ 764 public function test_delete_submission() { 765 766 // Create the submission that will be deleted. 767 $submissionid = $this->create_test_submission($this->student); 768 769 $this->setUser($this->student); 770 771 // Trigger and capture the event. 772 $sink = $this->redirectEvents(); 773 774 $result = mod_workshop_external::delete_submission($submissionid); 775 $result = external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result); 776 $this->assertEmpty($result['warnings']); 777 $this->assertTrue($result['status']); 778 $workshop = new workshop($this->workshop, $this->cm, $this->course); 779 $submission = $workshop->get_submission_by_author($this->student->id); 780 $this->assertFalse($submission); 781 782 $events = $sink->get_events(); 783 $this->assertCount(1, $events); 784 $event = array_shift($events); 785 786 // Checking event. 787 $this->assertInstanceOf('\mod_workshop\event\submission_deleted', $event); 788 $this->assertEquals($this->context, $event->get_context()); 789 } 790 791 /** 792 * Test test_delete_submission_with_assessments. 793 */ 794 public function test_delete_submission_with_assessments() { 795 796 // Create the submission that will be deleted. 797 $submissionid = $this->create_test_submission($this->student); 798 799 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 800 $workshopgenerator->create_assessment($submissionid, $this->teacher->id, array( 801 'weight' => 3, 802 'grade' => 95.00000, 803 )); 804 805 $this->setUser($this->student); 806 $this->expectException('moodle_exception'); 807 mod_workshop_external::delete_submission($submissionid); 808 } 809 810 /** 811 * Test test_delete_submission_invalid_phase. 812 */ 813 public function test_delete_submission_invalid_phase() { 814 815 // Create the submission that will be deleted. 816 $submissionid = $this->create_test_submission($this->student); 817 818 // Switch to assessment phase. 819 $workshop = new workshop($this->workshop, $this->cm, $this->course); 820 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 821 822 $this->setUser($this->student); 823 $this->expectException('moodle_exception'); 824 mod_workshop_external::delete_submission($submissionid); 825 } 826 827 /** 828 * Test test_delete_submission_as_teacher. 829 */ 830 public function test_delete_submission_as_teacher() { 831 832 // Create the submission that will be deleted. 833 $submissionid = $this->create_test_submission($this->student); 834 835 $this->setUser($this->teacher); 836 $result = mod_workshop_external::delete_submission($submissionid); 837 $result = external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result); 838 $this->assertEmpty($result['warnings']); 839 $this->assertTrue($result['status']); 840 } 841 842 /** 843 * Test test_delete_submission_other_user. 844 */ 845 public function test_delete_submission_other_user() { 846 847 $anotheruser = self::getDataGenerator()->create_user(); 848 $this->getDataGenerator()->enrol_user($anotheruser->id, $this->course->id, $this->studentrole->id, 'manual'); 849 // Create the submission that will be deleted. 850 $submissionid = $this->create_test_submission($this->student); 851 852 $this->setUser($anotheruser); 853 $this->expectException('moodle_exception'); 854 mod_workshop_external::delete_submission($submissionid); 855 } 856 857 /** 858 * Test test_get_submissions_student. 859 */ 860 public function test_get_submissions_student() { 861 862 // Create a couple of submissions with files. 863 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 864 $secondsubmissionid = $this->create_test_submission($this->anotherstudentg1); 865 866 $this->setUser($this->student); 867 $result = mod_workshop_external::get_submissions($this->workshop->id); 868 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 869 // We should get just our submission. 870 $this->assertCount(1, $result['submissions']); 871 $this->assertEquals(1, $result['totalcount']); 872 $this->assertEquals($firstsubmissionid, $result['submissions'][0]['id']); 873 $this->assertCount(1, $result['submissions'][0]['contentfiles']); // Check we retrieve submission text files. 874 $this->assertCount(1, $result['submissions'][0]['attachmentfiles']); // Check we retrieve attachment files. 875 // We shoul not see the grade or feedback information. 876 $properties = submission_exporter::properties_definition(); 877 foreach ($properties as $attribute => $settings) { 878 if (!empty($settings['optional'])) { 879 if (isset($result['submissions'][0][$attribute])) { 880 echo "error $attribute"; 881 } 882 $this->assertFalse(isset($result['submissions'][0][$attribute])); 883 } 884 } 885 } 886 887 /** 888 * Test test_get_submissions_published_student. 889 */ 890 public function test_get_submissions_published_student() { 891 892 $workshop = new workshop($this->workshop, $this->cm, $this->course); 893 $workshop->switch_phase(workshop::PHASE_CLOSED); 894 // Create a couple of submissions with files. 895 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 896 $submission = array('published' => 1); 897 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission); 898 899 $this->setUser($this->student); 900 $result = mod_workshop_external::get_submissions($this->workshop->id); 901 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 902 // We should get just our submission. 903 $this->assertCount(1, $result['submissions']); 904 $this->assertEquals(1, $result['totalcount']); 905 $this->assertEquals($submissionid, $result['submissions'][0]['id']); 906 907 // Check with group restrictions. 908 $this->setUser($this->anotherstudentg2); 909 $result = mod_workshop_external::get_submissions($this->workshop->id); 910 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 911 $this->assertCount(0, $result['submissions']); // I can't see other users in separated groups. 912 $this->assertEquals(0, $result['totalcount']); 913 } 914 915 /** 916 * Test test_get_submissions_from_student_with_feedback_from_teacher. 917 */ 918 public function test_get_submissions_from_student_with_feedback_from_teacher() { 919 global $DB; 920 921 // Create a couple of submissions with files. 922 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 923 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 924 // Create teacher feedback for submission. 925 $record = new \stdClass(); 926 $record->id = $submissionid; 927 $record->gradeover = 9; 928 $record->gradeoverby = $this->teacher->id; 929 $record->feedbackauthor = 'Hey'; 930 $record->feedbackauthorformat = FORMAT_MOODLE; 931 $record->published = 1; 932 $DB->update_record('workshop_submissions', $record); 933 934 // Remove teacher caps. 935 assign_capability('mod/workshop:viewallsubmissions', CAP_PROHIBIT, $this->teacher->id, $this->context->id); 936 // Empty all the caches that may be affected by this change. 937 accesslib_clear_all_caches_for_unit_testing(); 938 \course_modinfo::clear_instance_cache(); 939 940 $this->setUser($this->teacher); 941 $result = mod_workshop_external::get_submissions($this->workshop->id, $this->student->id); 942 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 943 // We should get just our submission. 944 $this->assertEquals(1, $result['totalcount']); 945 $this->assertEquals($submissionid, $result['submissions'][0]['id']); 946 } 947 948 /** 949 * Test test_get_submissions_from_students_as_teacher. 950 */ 951 public function test_get_submissions_from_students_as_teacher() { 952 953 // Create a couple of submissions with files. 954 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 955 $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 956 $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id); 957 $submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id); 958 959 $this->setUser($this->teacher); 960 $result = mod_workshop_external::get_submissions($this->workshop->id); // Get all. 961 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 962 $this->assertEquals(3, $result['totalcount']); 963 $this->assertCount(3, $result['submissions']); 964 965 $result = mod_workshop_external::get_submissions($this->workshop->id, 0, 0, 0, 2); // Check pagination. 966 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 967 $this->assertEquals(3, $result['totalcount']); 968 $this->assertCount(2, $result['submissions']); 969 970 $result = mod_workshop_external::get_submissions($this->workshop->id, 0, $this->group2->id); // Get group 2. 971 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 972 $this->assertEquals(1, $result['totalcount']); 973 $this->assertCount(1, $result['submissions']); 974 $this->assertEquals($submissionid3, $result['submissions'][0]['id']); 975 976 $result = mod_workshop_external::get_submissions($this->workshop->id, $this->anotherstudentg1->id); // Get one. 977 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 978 $this->assertEquals(1, $result['totalcount']); 979 $this->assertEquals($submissionid2, $result['submissions'][0]['id']); 980 } 981 982 /** 983 * Test test_get_submission_student. 984 */ 985 public function test_get_submission_student() { 986 987 // Create a couple of submissions with files. 988 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 989 990 $workshop = new workshop($this->workshop, $this->cm, $this->course); 991 $workshop->switch_phase(workshop::PHASE_CLOSED); 992 $this->setUser($this->student); 993 $result = mod_workshop_external::get_submission($firstsubmissionid); 994 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 995 $this->assertEquals($firstsubmissionid, $result['submission']['id']); 996 $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files. 997 $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files. 998 $this->assertArrayHasKey('feedbackauthor', $result['submission']); 999 $this->assertArrayNotHasKey('grade', $result['submission']); 1000 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1001 $this->assertArrayHasKey('gradeoverby', $result['submission']); 1002 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1003 1004 // Switch to a different phase (where feedback won't be available). 1005 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1006 $result = mod_workshop_external::get_submission($firstsubmissionid); 1007 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1008 $this->assertEquals($firstsubmissionid, $result['submission']['id']); 1009 $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files. 1010 $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files. 1011 $this->assertArrayNotHasKey('feedbackauthor', $result['submission']); 1012 $this->assertArrayNotHasKey('grade', $result['submission']); 1013 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1014 $this->assertArrayNotHasKey('gradeoverby', $result['submission']); 1015 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1016 } 1017 1018 /** 1019 * Test test_get_submission_i_reviewed. 1020 */ 1021 public function test_get_submission_i_reviewed() { 1022 1023 // Create a couple of submissions with files. 1024 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 1025 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1026 $workshopgenerator->create_assessment($firstsubmissionid, $this->anotherstudentg1->id, array( 1027 'weight' => 3, 1028 'grade' => 95, 1029 )); 1030 // Now try to get the submission I just reviewed. 1031 $this->setUser($this->anotherstudentg1); 1032 $result = mod_workshop_external::get_submission($firstsubmissionid); 1033 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1034 $this->assertEquals($firstsubmissionid, $result['submission']['id']); 1035 $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files. 1036 $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files. 1037 $this->assertArrayNotHasKey('feedbackauthor', $result['submission']); 1038 $this->assertArrayNotHasKey('grade', $result['submission']); 1039 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1040 $this->assertArrayNotHasKey('gradeoverby', $result['submission']); 1041 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1042 } 1043 1044 /** 1045 * Test test_get_submission_other_student. 1046 */ 1047 public function test_get_submission_other_student() { 1048 1049 // Create a couple of submissions with files. 1050 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 1051 // Expect failure. 1052 $this->setUser($this->anotherstudentg1); 1053 $this->expectException('moodle_exception'); 1054 $result = mod_workshop_external::get_submission($firstsubmissionid); 1055 } 1056 1057 /** 1058 * Test test_get_submission_published_student. 1059 */ 1060 public function test_get_submission_published_student() { 1061 1062 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1063 $workshop->switch_phase(workshop::PHASE_CLOSED); 1064 // Create a couple of submissions with files. 1065 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1066 $submission = array('published' => 1); 1067 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission); 1068 1069 $this->setUser($this->student); 1070 $result = mod_workshop_external::get_submission($submissionid); 1071 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1072 $this->assertEquals($submissionid, $result['submission']['id']); 1073 // Check that the student don't see the other student grade/feedback data even if is published. 1074 // We should not see the grade or feedback information. 1075 $properties = submission_exporter::properties_definition(); 1076 $this->assertArrayNotHasKey('feedbackauthor', $result['submission']); 1077 $this->assertArrayNotHasKey('grade', $result['submission']); 1078 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1079 $this->assertArrayNotHasKey('gradeoverby', $result['submission']); 1080 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1081 1082 // Check with group restrictions. 1083 $this->setUser($this->anotherstudentg2); 1084 $this->expectException('moodle_exception'); 1085 mod_workshop_external::get_submission($submissionid); 1086 } 1087 1088 /** 1089 * Test test_get_submission_from_student_with_feedback_from_teacher. 1090 */ 1091 public function test_get_submission_from_student_with_feedback_from_teacher() { 1092 global $DB; 1093 1094 // Create a couple of submissions with files. 1095 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1096 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1097 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1098 $workshop->switch_phase(workshop::PHASE_CLOSED); 1099 // Create teacher feedback for submission. 1100 $record = new \stdClass(); 1101 $record->id = $submissionid; 1102 $record->gradeover = 9; 1103 $record->gradeoverby = $this->teacher->id; 1104 $record->feedbackauthor = 'Hey'; 1105 $record->feedbackauthorformat = FORMAT_MOODLE; 1106 $record->published = 1; 1107 $record->timegraded = time(); 1108 $DB->update_record('workshop_submissions', $record); 1109 1110 $this->setUser($this->teacher); 1111 $result = mod_workshop_external::get_submission($submissionid); 1112 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1113 $this->assertEquals($submissionid, $result['submission']['id']); 1114 $this->assertEquals($record->feedbackauthor, $result['submission']['feedbackauthor']); 1115 $this->assertEquals($record->gradeover, $result['submission']['gradeover']); 1116 $this->assertEquals($record->gradeoverby, $result['submission']['gradeoverby']); 1117 $this->assertEquals($record->timegraded, $result['submission']['timegraded']); 1118 1119 // Go to phase where feedback and grades are not yet available. 1120 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 1121 $result = mod_workshop_external::get_submission($submissionid); 1122 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1123 $this->assertArrayNotHasKey('feedbackauthor', $result['submission']); 1124 $this->assertArrayNotHasKey('grade', $result['submission']); 1125 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1126 $this->assertArrayNotHasKey('gradeoverby', $result['submission']); 1127 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1128 1129 // Remove teacher caps to view and go to valid phase. 1130 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1131 unassign_capability('mod/workshop:viewallsubmissions', $this->teacherrole->id); 1132 // Empty all the caches that may be affected by this change. 1133 accesslib_clear_all_caches_for_unit_testing(); 1134 1135 $this->expectException('moodle_exception'); 1136 mod_workshop_external::get_submission($submissionid); 1137 } 1138 1139 /** 1140 * Test test_get_submission_from_students_as_teacher. 1141 */ 1142 public function test_get_submission_from_students_as_teacher() { 1143 // Create a couple of submissions with files. 1144 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1145 $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1146 $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id); 1147 $submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id); 1148 1149 $this->setUser($this->teacher); 1150 $result = mod_workshop_external::get_submission($submissionid1); // Get all. 1151 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1152 $this->assertEquals($submissionid1, $result['submission']['id']); 1153 1154 $result = mod_workshop_external::get_submission($submissionid3); // Get group 2. 1155 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1156 $this->assertEquals($submissionid3, $result['submission']['id']); 1157 } 1158 1159 1160 /** 1161 * Test get_submission_assessments_student. 1162 */ 1163 public function test_get_submission_assessments_student() { 1164 1165 // Create the submission that will be deleted. 1166 $submissionid = $this->create_test_submission($this->student); 1167 1168 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1169 $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1170 'weight' => 3, 1171 'grade' => 95, 1172 )); 1173 $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1174 'weight' => 2, 1175 'grade' => 90, 1176 )); 1177 1178 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1179 $workshop->switch_phase(workshop::PHASE_CLOSED); 1180 $this->setUser($this->student); 1181 $result = mod_workshop_external::get_submission_assessments($submissionid); 1182 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result); 1183 $this->assertCount(2, $result['assessments']); // I received my two assessments. 1184 foreach ($result['assessments'] as $assessment) { 1185 if ($assessment['grade'] == 90) { 1186 // My own assessment, I can see me. 1187 $this->assertEquals($this->student->id, $assessment['reviewerid']); 1188 } else { 1189 // Student's can't see who did the review. 1190 $this->assertEquals(0, $assessment['reviewerid']); 1191 } 1192 } 1193 } 1194 1195 /** 1196 * Test get_submission_assessments_invalid_phase. 1197 */ 1198 public function test_get_submission_assessments_invalid_phase() { 1199 1200 // Create the submission that will be deleted. 1201 $submissionid = $this->create_test_submission($this->student); 1202 1203 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1204 $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1205 'weight' => 3, 1206 'grade' => 95, 1207 )); 1208 1209 $this->expectException('moodle_exception'); 1210 mod_workshop_external::get_submission_assessments($submissionid); 1211 } 1212 1213 /** 1214 * Test get_submission_assessments_teacher. 1215 */ 1216 public function test_get_submission_assessments_teacher() { 1217 1218 // Create the submission that will be deleted. 1219 $submissionid = $this->create_test_submission($this->student); 1220 1221 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1222 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1223 'weight' => 1, 1224 'grade' => 50, 1225 )); 1226 1227 $this->setUser($this->teacher); 1228 $result = mod_workshop_external::get_submission_assessments($submissionid); 1229 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result); 1230 $this->assertCount(1, $result['assessments']); 1231 $this->assertEquals(50, $result['assessments'][0]['grade']); 1232 $this->assertEquals($assessmentid, $result['assessments'][0]['id']); 1233 } 1234 1235 /** 1236 * Test get_assessment_author. 1237 */ 1238 public function test_get_assessment_author() { 1239 1240 // Create the submission. 1241 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1242 1243 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1244 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1245 'weight' => 2, 1246 'grade' => 90, 1247 )); 1248 1249 // Switch to closed phase. 1250 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1251 $workshop->switch_phase(workshop::PHASE_CLOSED); 1252 $this->setUser($this->anotherstudentg1); 1253 $result = mod_workshop_external::get_assessment($assessmentid); 1254 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1255 $this->assertEquals($assessmentid, $result['assessment']['id']); 1256 $this->assertEquals(90, $result['assessment']['grade']); 1257 // I can't see the reviewer review. 1258 $this->assertFalse(isset($result['assessment']['feedbackreviewer'])); 1259 } 1260 1261 /** 1262 * Test get_assessment_reviewer. 1263 */ 1264 public function test_get_assessment_reviewer() { 1265 1266 // Create the submission. 1267 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1268 1269 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1270 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1271 'weight' => 2, 1272 'grade' => 90, 1273 )); 1274 1275 // Switch to closed phase. 1276 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1277 $workshop->switch_phase(workshop::PHASE_CLOSED); 1278 $this->setUser($this->student); 1279 $result = mod_workshop_external::get_assessment($assessmentid); 1280 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1281 $this->assertEquals($assessmentid, $result['assessment']['id']); 1282 $this->assertEquals(90, $result['assessment']['grade']); 1283 // I can see the reviewer review. 1284 $this->assertTrue(isset($result['assessment']['feedbackreviewer'])); 1285 } 1286 1287 /** 1288 * Test get_assessment_teacher. 1289 */ 1290 public function test_get_assessment_teacher() { 1291 1292 // Create the submission. 1293 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1294 1295 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1296 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1297 'weight' => 2, 1298 'grade' => 90, 1299 )); 1300 1301 // Switch to closed phase. 1302 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1303 $workshop->switch_phase(workshop::PHASE_CLOSED); 1304 $this->setUser($this->teacher); 1305 $result = mod_workshop_external::get_assessment($assessmentid); 1306 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1307 $this->assertEquals($assessmentid, $result['assessment']['id']); 1308 $this->assertEquals(90, $result['assessment']['grade']); 1309 } 1310 1311 /** 1312 * Test get_assessment_student_invalid_phase. 1313 */ 1314 public function test_get_assessment_student_invalid_phase() { 1315 1316 // Create the submission. 1317 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1318 1319 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1320 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1321 'weight' => 2, 1322 'grade' => 90, 1323 )); 1324 1325 // Switch to closed phase. 1326 $this->setUser($this->anotherstudentg1); 1327 1328 $this->expectException('moodle_exception'); 1329 mod_workshop_external::get_assessment($assessmentid); 1330 } 1331 1332 /** 1333 * Test get_assessment_student_invalid_user. 1334 */ 1335 public function test_get_assessment_student_invalid_user() { 1336 1337 // Create the submission. 1338 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1339 1340 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1341 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1342 'weight' => 2, 1343 'grade' => 90, 1344 )); 1345 1346 // Switch to closed phase. 1347 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1348 $workshop->switch_phase(workshop::PHASE_CLOSED); 1349 $this->setUser($this->anotherstudentg2); 1350 1351 $this->expectException('moodle_exception'); 1352 mod_workshop_external::get_assessment($assessmentid); 1353 } 1354 1355 /** 1356 * Test get_assessment_form_definition_reviewer_new_assessment. 1357 */ 1358 public function test_get_assessment_form_definition_reviewer_new_assessment() { 1359 1360 // Create the submission. 1361 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1362 1363 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1364 $submission = $workshop->get_submission_by_id($submissionid); 1365 $assessmentid = $workshop->add_allocation($submission, $this->student->id); 1366 1367 // Switch to assessment phase. 1368 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1369 $this->setUser($this->student); 1370 $result = mod_workshop_external::get_assessment_form_definition($assessmentid); 1371 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result); 1372 $this->assertEquals(4, $result['dimenssionscount']); // We receive the expected 4 dimensions. 1373 $this->assertEmpty($result['current']); // Assessment not yet done. 1374 foreach ($result['fields'] as $field) { 1375 if (strpos($field['name'], 'grade__idx_') === 0) { 1376 $this->assertEquals(25, $field['value']); // Check one of the dimension fields attributes. 1377 } 1378 } 1379 // Check dimensions grading info. 1380 foreach ($result['dimensionsinfo'] as $dimension) { 1381 $this->assertEquals(0, $dimension['min']); 1382 $this->assertEquals(25, $dimension['max']); 1383 $this->assertEquals(25, $dimension['weight']); 1384 $this->assertFalse(isset($dimension['scale'])); 1385 } 1386 } 1387 1388 /** 1389 * Test get_assessment_form_definition_teacher_new_assessment. 1390 */ 1391 public function test_get_assessment_form_definition_teacher_new_assessment() { 1392 1393 // Create the submission. 1394 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1395 1396 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1397 $submission = $workshop->get_submission_by_id($submissionid); 1398 $assessmentid = $workshop->add_allocation($submission, $this->student->id); 1399 1400 // Switch to assessment phase. 1401 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1402 // Teachers need to be able to view assessments. 1403 $this->setUser($this->teacher); 1404 $result = mod_workshop_external::get_assessment_form_definition($assessmentid); 1405 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result); 1406 $this->assertEquals(4, $result['dimenssionscount']); 1407 } 1408 1409 /** 1410 * Test get_assessment_form_definition_invalid_phase. 1411 */ 1412 public function test_get_assessment_form_definition_invalid_phase() { 1413 1414 // Create the submission. 1415 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1416 1417 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1418 $submission = $workshop->get_submission_by_id($submissionid); 1419 $assessmentid = $workshop->add_allocation($submission, $this->anotherstudentg1->id); 1420 1421 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1422 $this->setUser($this->student); 1423 // Since we are not reviewers we can't see the assessment until the workshop is closed. 1424 $this->expectException('moodle_exception'); 1425 mod_workshop_external::get_assessment_form_definition($assessmentid); 1426 } 1427 1428 /** 1429 * Test get_reviewer_assessments. 1430 */ 1431 public function test_get_reviewer_assessments() { 1432 1433 // Create the submission. 1434 $submissionid1 = $this->create_test_submission($this->student); 1435 $submissionid2 = $this->create_test_submission($this->anotherstudentg1); 1436 1437 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1438 $assessmentid1 = $workshopgenerator->create_assessment($submissionid1, $this->student->id, array( 1439 'weight' => 2, 1440 'grade' => 90, 1441 )); 1442 $assessmentid2 = $workshopgenerator->create_assessment($submissionid2, $this->student->id, array( 1443 'weight' => 3, 1444 'grade' => 80, 1445 )); 1446 1447 // Switch to assessment phase. 1448 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1449 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1450 $this->setUser($this->student); 1451 // Get my assessments. 1452 $result = mod_workshop_external::get_reviewer_assessments($this->workshop->id); 1453 $result = external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result); 1454 $this->assertCount(2, $result['assessments']); 1455 foreach ($result['assessments'] as $assessment) { 1456 if ($assessment['id'] == $assessmentid1) { 1457 $this->assertEquals(90, $assessment['grade']); 1458 } else { 1459 $this->assertEquals($assessmentid2, $assessment['id']); 1460 $this->assertEquals(80, $assessment['grade']); 1461 } 1462 } 1463 1464 // Now, as teacher try to get the same student assessments. 1465 $result = mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->student->id); 1466 $result = external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result); 1467 $this->assertCount(2, $result['assessments']); 1468 $this->assertArrayNotHasKey('feedbackreviewer', $result['assessments'][0]); 1469 } 1470 1471 /** 1472 * Test get_reviewer_assessments_other_student. 1473 */ 1474 public function test_get_reviewer_assessments_other_student() { 1475 1476 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1477 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1478 // Try to get other user assessments. 1479 $this->setUser($this->student); 1480 $this->expectException('moodle_exception'); 1481 mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id); 1482 } 1483 1484 /** 1485 * Test get_reviewer_assessments_invalid_phase. 1486 */ 1487 public function test_get_reviewer_assessments_invalid_phase() { 1488 1489 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1490 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 1491 // Try to get other user assessments. 1492 $this->setUser($this->student); 1493 $this->expectException('moodle_exception'); 1494 mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id); 1495 } 1496 1497 /** 1498 * Test update_assessment. 1499 */ 1500 public function test_update_assessment() { 1501 1502 // Create the submission. 1503 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1504 1505 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1506 $submission = $workshop->get_submission_by_id($submissionid); 1507 $assessmentid = $workshop->add_allocation($submission, $this->student->id); 1508 1509 // Switch to assessment phase. 1510 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1511 $this->setUser($this->student); 1512 // Get the form definition. 1513 $result = mod_workshop_external::get_assessment_form_definition($assessmentid); 1514 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result); 1515 1516 // Prepare the data to be sent. 1517 $data = $result['fields']; 1518 foreach ($data as $key => $param) { 1519 if (strpos($param['name'], 'peercomment__idx_') === 0) { 1520 $data[$key]['value'] = 'Some content'; 1521 } else if (strpos($param['name'], 'grade__idx_') === 0) { 1522 $data[$key]['value'] = 25; // Set all to 25. 1523 } 1524 } 1525 1526 // Required data. 1527 $data[] = array( 1528 'name' => 'nodims', 1529 'value' => $result['dimenssionscount'], 1530 ); 1531 1532 // General feedback. 1533 $data[] = array( 1534 'name' => 'feedbackauthor', 1535 'value' => 'Feedback for the author', 1536 ); 1537 $data[] = array( 1538 'name' => 'feedbackauthorformat', 1539 'value' => FORMAT_MOODLE, 1540 ); 1541 1542 // Create a file in a draft area for inline attachments. 1543 $fs = get_file_storage(); 1544 $draftidinlineattach = file_get_unused_draft_itemid(); 1545 $usercontext = \context_user::instance($this->student->id); 1546 $filenameimg = 'shouldbeanimage.txt'; 1547 $filerecordinline = array( 1548 'contextid' => $usercontext->id, 1549 'component' => 'user', 1550 'filearea' => 'draft', 1551 'itemid' => $draftidinlineattach, 1552 'filepath' => '/', 1553 'filename' => $filenameimg, 1554 ); 1555 $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); 1556 1557 // Create a file in a draft area for regular attachments. 1558 $draftidattach = file_get_unused_draft_itemid(); 1559 $filerecordattach = $filerecordinline; 1560 $attachfilename = 'attachment.txt'; 1561 $filerecordattach['filename'] = $attachfilename; 1562 $filerecordattach['itemid'] = $draftidattach; 1563 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 1564 1565 $data[] = array( 1566 'name' => 'feedbackauthorinlineattachmentsid', 1567 'value' => $draftidinlineattach, 1568 ); 1569 $data[] = array( 1570 'name' => 'feedbackauthorattachmentsid', 1571 'value' => $draftidattach, 1572 ); 1573 1574 // Update the assessment. 1575 $result = mod_workshop_external::update_assessment($assessmentid, $data); 1576 $result = external_api::clean_returnvalue(mod_workshop_external::update_assessment_returns(), $result); 1577 $this->assertEquals(100, $result['rawgrade']); 1578 $this->assertTrue($result['status']); 1579 1580 // Get the assessment and check it was updated properly. 1581 $result = mod_workshop_external::get_assessment($assessmentid); 1582 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1583 $this->assertEquals(100, $result['assessment']['grade']); 1584 $this->assertEquals($this->student->id, $result['assessment']['reviewerid']); 1585 $this->assertEquals('Feedback for the author', $result['assessment']['feedbackauthor']); 1586 $this->assertCount(1, $result['assessment']['feedbackcontentfiles']); 1587 $this->assertCount(1, $result['assessment']['feedbackattachmentfiles']); 1588 1589 // Now, get again the form and check we received the data we already sent. 1590 $result = mod_workshop_external::get_assessment_form_definition($assessmentid); 1591 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result); 1592 foreach ($result['current'] as $currentdata) { 1593 if (strpos($currentdata['name'], 'peercomment__idx_') === 0) { 1594 $this->assertEquals('Some content', $currentdata['value']); 1595 } else if (strpos($currentdata['name'], 'grade__idx_') === 0) { 1596 $this->assertEquals(25, (int) $currentdata['value']); 1597 } 1598 } 1599 } 1600 1601 /** 1602 * Test get_grades. 1603 */ 1604 public function test_get_grades() { 1605 1606 $timenow = time(); 1607 $submissiongrade = array( 1608 'userid' => $this->student->id, 1609 'rawgrade' => 40, 1610 'feedback' => '', 1611 'feedbackformat' => 1, 1612 'datesubmitted' => $timenow, 1613 'dategraded' => $timenow, 1614 ); 1615 $assessmentgrade = array( 1616 'userid' => $this->student->id, 1617 'rawgrade' => 10, 1618 'feedback' => '', 1619 'feedbackformat' => 1, 1620 'datesubmitted' => $timenow, 1621 'dategraded' => $timenow, 1622 ); 1623 1624 workshop_grade_item_update($this->workshop, (object) $submissiongrade, (object) $assessmentgrade); 1625 1626 // First retrieve my grades. 1627 $this->setUser($this->student); 1628 $result = mod_workshop_external::get_grades($this->workshop->id); 1629 $result = external_api::clean_returnvalue(mod_workshop_external::get_grades_returns(), $result); 1630 $this->assertCount(0, $result['warnings']); 1631 $this->assertEquals($assessmentgrade['rawgrade'], $result['assessmentrawgrade']); 1632 $this->assertEquals($submissiongrade['rawgrade'], $result['submissionrawgrade']); 1633 $this->assertFalse($result['assessmentgradehidden']); 1634 $this->assertFalse($result['submissiongradehidden']); 1635 $this->assertEquals($assessmentgrade['rawgrade'] . ".00 / 20.00", $result['assessmentlongstrgrade']); 1636 $this->assertEquals($submissiongrade['rawgrade'] . ".00 / 80.00", $result['submissionlongstrgrade']); 1637 1638 // Second, teacher retrieve user grades. 1639 $this->setUser($this->teacher); 1640 $result = mod_workshop_external::get_grades($this->workshop->id, $this->student->id); 1641 $result = external_api::clean_returnvalue(mod_workshop_external::get_grades_returns(), $result); 1642 $this->assertCount(0, $result['warnings']); 1643 $this->assertEquals($assessmentgrade['rawgrade'], $result['assessmentrawgrade']); 1644 $this->assertEquals($submissiongrade['rawgrade'], $result['submissionrawgrade']); 1645 $this->assertFalse($result['assessmentgradehidden']); 1646 $this->assertFalse($result['submissiongradehidden']); 1647 $this->assertEquals($assessmentgrade['rawgrade'] . ".00 / 20.00", $result['assessmentlongstrgrade']); 1648 $this->assertEquals($submissiongrade['rawgrade'] . ".00 / 80.00", $result['submissionlongstrgrade']); 1649 } 1650 1651 /** 1652 * Test get_grades_other_student. 1653 */ 1654 public function test_get_grades_other_student() { 1655 1656 // Create the submission that will be deleted. 1657 $submissionid = $this->create_test_submission($this->student); 1658 1659 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1660 $workshop->switch_phase(workshop::PHASE_CLOSED); 1661 $this->setUser($this->anotherstudentg1); 1662 $this->expectException('moodle_exception'); 1663 mod_workshop_external::get_grades($this->workshop->id, $this->student->id); 1664 } 1665 1666 /** 1667 * Test evaluate_assessment. 1668 */ 1669 public function test_evaluate_assessment() { 1670 global $DB; 1671 1672 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1673 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1674 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1675 'weight' => 3, 1676 'grade' => 20, 1677 )); 1678 1679 $this->setUser($this->teacher); 1680 $feedbacktext = 'The feedback'; 1681 $feedbackformat = FORMAT_MOODLE; 1682 $weight = 10; 1683 $gradinggradeover = 10; 1684 $result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, 1685 $gradinggradeover); 1686 $result = external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result); 1687 $this->assertTrue($result['status']); 1688 1689 $assessment = $DB->get_record('workshop_assessments', array('id' => $assessmentid)); 1690 $this->assertEquals('The feedback', $assessment->feedbackreviewer); 1691 $this->assertEquals(10, $assessment->weight); 1692 1693 // Now test passing incorrect weight and grade values. 1694 $weight = 17; 1695 $gradinggradeover = 100; 1696 $result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, 1697 $gradinggradeover); 1698 $result = external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result); 1699 $this->assertFalse($result['status']); 1700 $this->assertCount(2, $result['warnings']); 1701 $found = 0; 1702 foreach ($result['warnings'] as $warning) { 1703 if ($warning['item'] == 'weight' || $warning['item'] == 'gradinggradeover') { 1704 $found++; 1705 } 1706 } 1707 $this->assertEquals(2, $found); 1708 } 1709 1710 /** 1711 * Test evaluate_assessment_ignore_parameters. 1712 */ 1713 public function test_evaluate_assessment_ignore_parameters() { 1714 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1715 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1716 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1717 'weight' => 3, 1718 'grade' => 20, 1719 )); 1720 1721 assign_capability('mod/workshop:allocate', CAP_PROHIBIT, $this->teacherrole->id, $this->context->id); 1722 // Empty all the caches that may be affected by this change. 1723 accesslib_clear_all_caches_for_unit_testing(); 1724 1725 $this->setUser($this->teacher); 1726 $feedbacktext = 'The feedback'; 1727 $feedbackformat = FORMAT_MOODLE; 1728 $weight = 10; 1729 $gradinggradeover = 19; 1730 $result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, 1731 $gradinggradeover); 1732 $result = external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result); 1733 $this->assertTrue($result['status']); 1734 1735 $result = mod_workshop_external::get_assessment($assessmentid); 1736 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1737 $this->assertNotEquals(10, $result['assessment']['weight']); 1738 } 1739 1740 /** 1741 * Test evaluate_assessment_no_permissions. 1742 */ 1743 public function test_evaluate_assessment_no_permissions() { 1744 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1745 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1746 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1747 'weight' => 3, 1748 'grade' => 20, 1749 )); 1750 1751 $this->setUser($this->student); 1752 $feedbacktext = 'The feedback'; 1753 $feedbackformat = FORMAT_MOODLE; 1754 $weight = 10; 1755 $gradinggradeover = 50; 1756 $this->expectException('moodle_exception'); 1757 mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, $gradinggradeover); 1758 } 1759 1760 /** 1761 * Test get_grades_report. 1762 */ 1763 public function test_get_grades_report() { 1764 1765 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1766 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1767 $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1768 $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id); 1769 1770 $assessmentid1 = $workshopgenerator->create_assessment($submissionid2, $this->student->id, array( 1771 'weight' => 100, 1772 'grade' => 50, 1773 )); 1774 $assessmentid2 = $workshopgenerator->create_assessment($submissionid1, $this->anotherstudentg1->id, array( 1775 'weight' => 100, 1776 'grade' => 55, 1777 )); 1778 1779 $workshop->switch_phase(workshop::PHASE_CLOSED); 1780 $this->setUser($this->teacher); 1781 $result = mod_workshop_external::get_grades_report($this->workshop->id); 1782 $result = external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result); 1783 $this->assertEquals(3, $result['report']['totalcount']); // Expect 3 potential submissions. 1784 1785 foreach ($result['report']['grades'] as $grade) { 1786 if ($grade['userid'] == $this->student->id) { 1787 $this->assertEquals($this->anotherstudentg1->id, $grade['reviewedby'][0]['userid']); // Check reviewer. 1788 $this->assertEquals($this->anotherstudentg1->id, $grade['reviewerof'][0]['userid']); // Check reviewer. 1789 $this->assertEquals($workshop->real_grade(50), $grade['reviewerof'][0]['grade']); // Check grade (converted). 1790 $this->assertEquals($workshop->real_grade(55), $grade['reviewedby'][0]['grade']); // Check grade (converted). 1791 } else if ($grade['userid'] == $this->anotherstudentg1->id) { 1792 $this->assertEquals($this->student->id, $grade['reviewedby'][0]['userid']); // Check reviewer. 1793 $this->assertEquals($this->student->id, $grade['reviewerof'][0]['userid']); // Check reviewer. 1794 $this->assertEquals($workshop->real_grade(55), $grade['reviewerof'][0]['grade']); // Check grade (converted). 1795 $this->assertEquals($workshop->real_grade(50), $grade['reviewedby'][0]['grade']); // Check grade (converted). 1796 } 1797 } 1798 // Now check pagination. 1799 $result = mod_workshop_external::get_grades_report($this->workshop->id, 0, 'lastname', 'ASC', 0, 1); 1800 $result = external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result); 1801 $this->assertEquals(3, $result['report']['totalcount']); // Expect the total count. 1802 $this->assertCount(1, $result['report']['grades']); 1803 1804 // Groups filtering. 1805 $result = mod_workshop_external::get_grades_report($this->workshop->id, $this->group1->id); 1806 $result = external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result); 1807 $this->assertEquals(2, $result['report']['totalcount']); // Expect the group count. 1808 } 1809 1810 /** 1811 * Test get_grades_report_invalid_phase. 1812 */ 1813 public function test_get_grades_report_invalid_phase() { 1814 $this->setUser($this->teacher); 1815 $this->expectException('moodle_exception'); 1816 $this->expectExceptionMessage(get_string('nothingfound', 'workshop')); 1817 mod_workshop_external::get_grades_report($this->workshop->id); 1818 } 1819 1820 /** 1821 * Test get_grades_report_missing_permissions. 1822 */ 1823 public function test_get_grades_report_missing_permissions() { 1824 $this->setUser($this->student); 1825 $this->expectException('required_capability_exception'); 1826 mod_workshop_external::get_grades_report($this->workshop->id); 1827 } 1828 1829 /** 1830 * Test test_view_submission. 1831 */ 1832 public function test_view_submission() { 1833 1834 // Create a couple of submissions with files. 1835 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 1836 1837 // Trigger and capture the event. 1838 $sink = $this->redirectEvents(); 1839 1840 $this->setUser($this->student); 1841 $result = mod_workshop_external::view_submission($firstsubmissionid); 1842 $result = external_api::clean_returnvalue(mod_workshop_external::view_submission_returns(), $result); 1843 1844 $events = $sink->get_events(); 1845 $this->assertCount(1, $events); 1846 $event = array_shift($events); 1847 1848 // Checking that the event contains the expected values. 1849 $this->assertInstanceOf('\mod_workshop\event\submission_viewed', $event); 1850 $this->assertEquals($this->context, $event->get_context()); 1851 $moodleworkshop = new \moodle_url('/mod/workshop/submission.php', array('id' => $firstsubmissionid, 1852 'cmid' => $this->cm->id)); 1853 $this->assertEquals($moodleworkshop, $event->get_url()); 1854 $this->assertEventContextNotUsed($event); 1855 $this->assertNotEmpty($event->get_name()); 1856 1857 } 1858 1859 /** 1860 * Test evaluate_submission. 1861 */ 1862 public function test_evaluate_submission() { 1863 global $DB; 1864 1865 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1866 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1867 1868 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1869 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1870 1871 $this->setUser($this->teacher); 1872 $feedbacktext = 'The feedback'; 1873 $feedbackformat = FORMAT_MOODLE; 1874 $published = 1; 1875 $gradeover = 10; 1876 $result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, 1877 $gradeover); 1878 $result = external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result); 1879 $this->assertTrue($result['status']); 1880 1881 $submission = $DB->get_record('workshop_submissions', array('id' => $submissionid)); 1882 $this->assertEquals($feedbacktext, $submission->feedbackauthor); 1883 $this->assertEquals($workshop->raw_grade_value($gradeover, $workshop->grade), $submission->gradeover); // Expected grade. 1884 $this->assertEquals(1, $submission->published); // Submission published. 1885 } 1886 1887 /** 1888 * Test evaluate_submission_invalid_phase_for_override. 1889 */ 1890 public function test_evaluate_submission_invalid_phase_for_override() { 1891 global $DB; 1892 1893 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1894 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1895 1896 $this->setUser($this->teacher); 1897 $feedbacktext = 'The feedback'; 1898 $feedbackformat = FORMAT_MOODLE; 1899 $published = 1; 1900 $gradeover = 10; 1901 $result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, 1902 $gradeover); 1903 $result = external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result); 1904 $this->assertTrue($result['status']); 1905 1906 $submission = $DB->get_record('workshop_submissions', array('id' => $submissionid)); 1907 $this->assertEquals('', $submission->feedbackauthor); // Feedback and grade not updated. 1908 $this->assertEquals(0, $submission->gradeover); 1909 $this->assertEquals(1, $submission->published); // Publishing status correctly updated. 1910 } 1911 1912 /** 1913 * Test evaluate_submission_no_permissions. 1914 */ 1915 public function test_evaluate_submission_no_permissions() { 1916 1917 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1918 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1919 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1920 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1921 1922 $this->setUser($this->student); 1923 $feedbacktext = 'The feedback'; 1924 $feedbackformat = FORMAT_MOODLE; 1925 $published = 1; 1926 $gradeover = 50; 1927 $this->expectException('moodle_exception'); 1928 mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, $gradeover); 1929 } 1930 1931 /** 1932 * Test evaluate_submission_invalid_grade. 1933 */ 1934 public function test_evaluate_submission_invalid_grade() { 1935 1936 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1937 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1938 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1939 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1940 1941 $this->setUser($this->teacher); 1942 $feedbacktext = 'The feedback'; 1943 $feedbackformat = FORMAT_MOODLE; 1944 $published = 1; 1945 $gradeover = 150; 1946 $result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, $gradeover); 1947 $result = external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result); 1948 $this->assertCount(1, $result['warnings']); 1949 $this->assertFalse($result['status']); 1950 $this->assertEquals('gradeover', $result['warnings'][0]['item']); 1951 } 1952 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body