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