[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 * Unit tests for (some of) mod/assign/locallib.php. 19 * 20 * @package mod_assign 21 * @category phpunit 22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 global $CFG; 30 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 31 require_once($CFG->dirroot . '/mod/assign/upgradelib.php'); 32 require_once($CFG->dirroot . '/mod/assign/tests/base_test.php'); 33 34 /** 35 * Unit tests for (some of) mod/assign/locallib.php. 36 * 37 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class mod_assign_locallib_testcase extends mod_assign_base_testcase { 41 42 public function test_return_links() { 43 global $PAGE; 44 $this->setUser($this->editingteachers[0]); 45 $returnaction = 'RETURNACTION'; 46 $returnparams = array('param'=>'1'); 47 $assign = $this->create_instance(); 48 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 49 $assign->register_return_link($returnaction, $returnparams); 50 $this->assertEquals($returnaction, $assign->get_return_action()); 51 $this->assertEquals($returnparams, $assign->get_return_params()); 52 } 53 54 public function test_get_feedback_plugins() { 55 $this->setUser($this->editingteachers[0]); 56 $assign = $this->create_instance(); 57 $installedplugins = array_keys(core_component::get_plugin_list('assignfeedback')); 58 59 foreach ($assign->get_feedback_plugins() as $plugin) { 60 $this->assertContains($plugin->get_type(), $installedplugins, 'Feedback plugin not in list of installed plugins'); 61 } 62 } 63 64 public function test_get_submission_plugins() { 65 $this->setUser($this->editingteachers[0]); 66 $assign = $this->create_instance(); 67 $installedplugins = array_keys(core_component::get_plugin_list('assignsubmission')); 68 69 foreach ($assign->get_submission_plugins() as $plugin) { 70 $this->assertContains($plugin->get_type(), $installedplugins, 'Submission plugin not in list of installed plugins'); 71 } 72 } 73 74 public function test_is_blind_marking() { 75 $this->setUser($this->editingteachers[0]); 76 $assign = $this->create_instance(array('blindmarking'=>1)); 77 $this->assertEquals(true, $assign->is_blind_marking()); 78 79 // Test cannot see student names. 80 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 81 $output = $assign->get_renderer()->render($gradingtable); 82 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign'))); 83 84 // Test students cannot reveal identities. 85 $nopermission = false; 86 $this->students[0]->ignoresesskey = true; 87 $this->setUser($this->students[0]); 88 $this->expectException('required_capability_exception'); 89 $assign->reveal_identities(); 90 $this->students[0]->ignoresesskey = false; 91 92 // Test teachers cannot reveal identities. 93 $nopermission = false; 94 $this->teachers[0]->ignoresesskey = true; 95 $this->setUser($this->teachers[0]); 96 $this->expectException('required_capability_exception'); 97 $assign->reveal_identities(); 98 $this->teachers[0]->ignoresesskey = false; 99 100 // Test sesskey is required. 101 $this->setUser($this->editingteachers[0]); 102 $this->expectException('moodle_exception'); 103 $assign->reveal_identities(); 104 105 // Test editingteacher can reveal identities if sesskey is ignored. 106 $this->editingteachers[0]->ignoresesskey = true; 107 $this->setUser($this->editingteachers[0]); 108 $assign->reveal_identities(); 109 $this->assertEquals(false, $assign->is_blind_marking()); 110 $this->editingteachers[0]->ignoresesskey = false; 111 112 // Test student names are visible. 113 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 114 $output = $assign->get_renderer()->render($gradingtable); 115 $this->assertEquals(false, strpos($output, get_string('hiddenuser', 'assign'))); 116 117 // Set this back to default. 118 $this->editingteachers[0]->ignoresesskey = false; 119 } 120 121 /** 122 * Data provider for test_get_assign_perpage 123 * 124 * @return array Provider data 125 */ 126 public function get_assign_perpage_provider() { 127 return array( 128 array( 129 'maxperpage' => -1, 130 'userprefs' => array( 131 -1 => -1, 132 10 => 10, 133 20 => 20, 134 50 => 50, 135 ), 136 ), 137 array( 138 'maxperpage' => 15, 139 'userprefs' => array( 140 -1 => 15, 141 10 => 10, 142 20 => 15, 143 50 => 15, 144 ), 145 ), 146 ); 147 } 148 149 /** 150 * Test maxperpage 151 * 152 * @dataProvider get_assign_perpage_provider 153 * @param integer $maxperpage site config value 154 * @param array $userprefs Array of user preferences and expected page sizes 155 */ 156 public function test_get_assign_perpage($maxperpage, $userprefs) { 157 158 $this->setUser($this->editingteachers[0]); 159 $assign = $this->create_instance(); 160 set_config('maxperpage', $maxperpage, 'assign'); 161 set_user_preference('assign_perpage', null); 162 $this->assertEquals(10, $assign->get_assign_perpage()); 163 foreach ($userprefs as $pref => $perpage) { 164 set_user_preference('assign_perpage', $pref); 165 $this->assertEquals($perpage, $assign->get_assign_perpage()); 166 } 167 } 168 169 /** 170 * Test submissions with extension date. 171 */ 172 public function test_gradingtable_extension_due_date() { 173 global $PAGE; 174 175 // Setup the assignment. 176 $this->create_extra_users(); 177 $this->setUser($this->editingteachers[0]); 178 $assign = $this->create_instance(array( 179 'assignsubmission_onlinetext_enabled'=>1, 180 'duedate' => time() - 4 * 24 * 60 * 60, 181 )); 182 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array( 183 'id' => $assign->get_course_module()->id, 184 'action' => 'grading', 185 ))); 186 187 // Check that the assignment is late. 188 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 189 $output = $assign->get_renderer()->render($gradingtable); 190 $this->assertContains(get_string('submissionstatus_', 'assign'), $output); 191 $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60)), $output); 192 193 // Grant an extension. 194 $extendedtime = time() + 2 * 24 * 60 * 60; 195 $assign->testable_save_user_extension($this->students[0]->id, $extendedtime); 196 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 197 $output = $assign->get_renderer()->render($gradingtable); 198 $this->assertContains(get_string('submissionstatus_', 'assign'), $output); 199 $this->assertContains(get_string('userextensiondate', 'assign', userdate($extendedtime)), $output); 200 201 // Simulate a submission. 202 $this->setUser($this->students[0]); 203 $submission = $assign->get_user_submission($this->students[0]->id, true); 204 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 205 $assign->testable_update_submission($submission, $this->students[0]->id, true, false); 206 $data = new stdClass(); 207 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 208 'text'=>'Submission text', 209 'format'=>FORMAT_MOODLE); 210 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 211 $plugin->save($submission, $data); 212 213 // Verify output. 214 $this->setUser($this->editingteachers[0]); 215 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 216 $output = $assign->get_renderer()->render($gradingtable); 217 $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output); 218 $this->assertContains(get_string('userextensiondate', 'assign', userdate($extendedtime)), $output); 219 } 220 221 /** 222 * Test that late submissions with extension date calculate correctly. 223 */ 224 public function test_gradingtable_extension_date_calculation_for_lateness() { 225 global $PAGE; 226 227 // Setup the assignment. 228 $this->create_extra_users(); 229 $this->setUser($this->editingteachers[0]); 230 $time = time(); 231 $assign = $this->create_instance(array( 232 'assignsubmission_onlinetext_enabled'=>1, 233 'duedate' => $time - 4 * 24 * 60 * 60, 234 )); 235 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array( 236 'id' => $assign->get_course_module()->id, 237 'action' => 'grading', 238 ))); 239 240 // Check that the assignment is late. 241 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 242 $output = $assign->get_renderer()->render($gradingtable); 243 $this->assertContains(get_string('submissionstatus_', 'assign'), $output); 244 $difftime = time() - $time; 245 $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60 + $difftime)), $output); 246 247 // Grant an extension that is in the past. 248 $assign->testable_save_user_extension($this->students[0]->id, $time - 2 * 24 * 60 * 60); 249 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 250 $output = $assign->get_renderer()->render($gradingtable); 251 $this->assertContains(get_string('submissionstatus_', 'assign'), $output); 252 $this->assertContains(get_string('userextensiondate', 'assign', userdate($time - 2*24*60*60)), $output); 253 $difftime = time() - $time; 254 $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60 + $difftime)), $output); 255 256 // Simulate a submission. 257 $this->setUser($this->students[0]); 258 $submission = $assign->get_user_submission($this->students[0]->id, true); 259 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 260 $assign->testable_update_submission($submission, $this->students[0]->id, true, false); 261 $data = new stdClass(); 262 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 263 'text'=>'Submission text', 264 'format'=>FORMAT_MOODLE); 265 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 266 $plugin->save($submission, $data); 267 $submittedtime = time(); 268 269 // Verify output. 270 $this->setUser($this->editingteachers[0]); 271 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 272 $output = $assign->get_renderer()->render($gradingtable); 273 $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output); 274 $this->assertContains(get_string('userextensiondate', 'assign', userdate($time - 2*24*60*60)), $output); 275 276 $difftime = $submittedtime - $time; 277 $this->assertContains(get_string('submittedlateshort', 'assign', format_time(2*24*60*60 + $difftime)), $output); 278 } 279 280 public function test_gradingtable_status_rendering() { 281 global $PAGE; 282 283 // Setup the assignment. 284 $this->create_extra_users(); 285 $this->setUser($this->editingteachers[0]); 286 $time = time(); 287 $assign = $this->create_instance(array( 288 'assignsubmission_onlinetext_enabled' => 1, 289 'duedate' => $time - 4 * 24 * 60 * 60, 290 )); 291 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array( 292 'id' => $assign->get_course_module()->id, 293 'action' => 'grading', 294 ))); 295 296 // Check that the assignment is late. 297 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 298 $output = $assign->get_renderer()->render($gradingtable); 299 $this->assertContains(get_string('submissionstatus_', 'assign'), $output); 300 $difftime = time() - $time; 301 $this->assertContains(get_string('overdue', 'assign', format_time(4 * 24 * 60 * 60 + $difftime)), $output); 302 303 // Simulate a student viewing the assignment without submitting. 304 $this->setUser($this->students[0]); 305 $submission = $assign->get_user_submission($this->students[0]->id, true); 306 $submission->status = ASSIGN_SUBMISSION_STATUS_NEW; 307 $assign->testable_update_submission($submission, $this->students[0]->id, true, false); 308 $submittedtime = time(); 309 310 // Verify output. 311 $this->setUser($this->editingteachers[0]); 312 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 313 $output = $assign->get_renderer()->render($gradingtable); 314 $difftime = $submittedtime - $time; 315 $this->assertContains(get_string('overdue', 'assign', format_time(4 * 24 * 60 * 60 + $difftime)), $output); 316 317 $document = new DOMDocument(); 318 $document->loadHTML($output); 319 $xpath = new DOMXPath($document); 320 $this->assertEquals('', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])')); 321 } 322 323 /** 324 * Check that group submission information is rendered correctly in the 325 * grading table. 326 */ 327 public function test_gradingtable_group_submissions_rendering() { 328 global $PAGE; 329 330 $this->create_extra_users(); 331 // Now verify group assignments. 332 $this->setUser($this->teachers[0]); 333 $assign = $this->create_instance(array( 334 'teamsubmission' => 1, 335 'assignsubmission_onlinetext_enabled' => 1, 336 'submissiondrafts' => 1, 337 'requireallteammemberssubmit' => 0, 338 )); 339 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array( 340 'id' => $assign->get_course_module()->id, 341 'action' => 'grading', 342 ))); 343 344 // Add a submission. 345 $this->setUser($this->extrastudents[0]); 346 $data = new stdClass(); 347 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 348 'text'=>'Submission text', 349 'format'=>FORMAT_MOODLE); 350 $notices = array(); 351 $assign->save_submission($data, $notices); 352 353 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true); 354 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 355 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true); 356 357 // Check output. 358 $this->setUser($this->teachers[0]); 359 $gradingtable = new assign_grading_table($assign, 4, '', 0, true); 360 $output = $assign->get_renderer()->render($gradingtable); 361 $document = new DOMDocument(); 362 $document->loadHTML($output); 363 $xpath = new DOMXPath($document); 364 365 // Check status. 366 $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c4"]/div[@class="submissionstatussubmitted"])')); 367 $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c4"]/div[@class="submissionstatussubmitted"])')); 368 369 // Check submission last modified date 370 $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])'))); 371 $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c8"])'))); 372 373 // Check group. 374 $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c5"])')); 375 $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c5"])')); 376 377 // Check submission text. 378 $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c9"]/div/div)')); 379 $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c9"]/div/div)')); 380 381 // Check comments can be made. 382 $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r0_c10"]//textarea)')); 383 $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r3_c10"]//textarea)')); 384 } 385 386 public function test_show_intro() { 387 // Test whether we are showing the intro at the correct times. 388 $this->setUser($this->editingteachers[0]); 389 $assign = $this->create_instance(array('alwaysshowdescription'=>1)); 390 391 $this->assertEquals(true, $assign->testable_show_intro()); 392 393 $tomorrow = time() + (24*60*60); 394 395 $assign = $this->create_instance(array('alwaysshowdescription'=>0, 396 'allowsubmissionsfromdate'=>$tomorrow)); 397 $this->assertEquals(false, $assign->testable_show_intro()); 398 $yesterday = time() - (24*60*60); 399 $assign = $this->create_instance(array('alwaysshowdescription'=>0, 400 'allowsubmissionsfromdate'=>$yesterday)); 401 $this->assertEquals(true, $assign->testable_show_intro()); 402 } 403 404 public function test_has_submissions_or_grades() { 405 $this->setUser($this->editingteachers[0]); 406 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1)); 407 408 $instance = $assign->get_instance(); 409 410 // Should start empty. 411 $this->assertEquals(false, $assign->has_submissions_or_grades()); 412 413 // Simulate a submission. 414 $this->setUser($this->students[0]); 415 $submission = $assign->get_user_submission($this->students[0]->id, true); 416 417 // The submission is still new. 418 $this->assertEquals(false, $assign->has_submissions_or_grades()); 419 420 // Submit the submission. 421 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 422 $assign->testable_update_submission($submission, $this->students[0]->id, true, false); 423 $data = new stdClass(); 424 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 425 'text'=>'Submission text', 426 'format'=>FORMAT_MOODLE); 427 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 428 $plugin->save($submission, $data); 429 430 // Now test again. 431 $this->assertEquals(true, $assign->has_submissions_or_grades()); 432 // Set this back to default. 433 $this->students[0]->ignoresesskey = false; 434 } 435 436 public function test_delete_grades() { 437 $this->setUser($this->editingteachers[0]); 438 $assign = $this->create_instance(); 439 440 // Simulate adding a grade. 441 $this->setUser($this->teachers[0]); 442 $data = new stdClass(); 443 $data->grade = '50.0'; 444 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 445 446 // Now see if the data is in the gradebook. 447 $gradinginfo = grade_get_grades($this->course->id, 448 'mod', 449 'assign', 450 $assign->get_instance()->id); 451 452 $this->assertNotEquals(0, count($gradinginfo->items)); 453 454 $assign->testable_delete_grades(); 455 $gradinginfo = grade_get_grades($this->course->id, 456 'mod', 457 'assign', 458 $assign->get_instance()->id); 459 460 $this->assertEquals(0, count($gradinginfo->items)); 461 } 462 463 public function test_delete_instance() { 464 $this->setUser($this->editingteachers[0]); 465 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1)); 466 467 // Simulate adding a grade. 468 $this->setUser($this->teachers[0]); 469 $data = new stdClass(); 470 $data->grade = '50.0'; 471 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 472 473 // Simulate a submission. 474 $this->setUser($this->students[0]); 475 $submission = $assign->get_user_submission($this->students[0]->id, true); 476 $data = new stdClass(); 477 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 478 'text'=>'Submission text', 479 'format'=>FORMAT_MOODLE); 480 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 481 $plugin->save($submission, $data); 482 483 // Now try and delete. 484 $this->assertEquals(true, $assign->delete_instance()); 485 } 486 487 public function test_reset_userdata() { 488 global $DB; 489 490 $now = time(); 491 $this->setUser($this->editingteachers[0]); 492 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 493 'duedate'=>$now)); 494 495 // Simulate adding a grade. 496 $this->setUser($this->teachers[0]); 497 $data = new stdClass(); 498 $data->grade = '50.0'; 499 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 500 501 // Simulate a submission. 502 $this->setUser($this->students[0]); 503 $submission = $assign->get_user_submission($this->students[0]->id, true); 504 $data = new stdClass(); 505 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 506 'text'=>'Submission text', 507 'format'=>FORMAT_MOODLE); 508 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 509 $plugin->save($submission, $data); 510 511 $this->assertEquals(true, $assign->has_submissions_or_grades()); 512 // Now try and reset. 513 $data = new stdClass(); 514 $data->reset_assign_submissions = 1; 515 $data->reset_gradebook_grades = 1; 516 $data->courseid = $this->course->id; 517 $data->timeshift = 24*60*60; 518 $this->setUser($this->editingteachers[0]); 519 $assign->reset_userdata($data); 520 $this->assertEquals(false, $assign->has_submissions_or_grades()); 521 522 // Reload the instance data. 523 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id)); 524 $this->assertEquals($now + 24*60*60, $instance->duedate); 525 526 // Test reset using assign_reset_userdata(). 527 $assignduedate = $instance->duedate; // Keep old updated value for comparison. 528 $data->timeshift = 2*24*60*60; 529 assign_reset_userdata($data); 530 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id)); 531 $this->assertEquals($assignduedate + 2*24*60*60, $instance->duedate); 532 533 // Create one more assignment and reset, make sure time shifted for previous assignment is not changed. 534 $assign2 = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1, 535 'duedate' => $now)); 536 $assignduedate = $instance->duedate; 537 $data->timeshift = 3*24*60*60; 538 $assign2->reset_userdata($data); 539 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id)); 540 $this->assertEquals($assignduedate, $instance->duedate); 541 $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id)); 542 $this->assertEquals($now + 3*24*60*60, $instance2->duedate); 543 544 // Reset both assignments using assign_reset_userdata() and make sure both assignments have same date. 545 $assignduedate = $instance->duedate; 546 $assign2duedate = $instance2->duedate; 547 $data->timeshift = 4*24*60*60; 548 assign_reset_userdata($data); 549 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id)); 550 $this->assertEquals($assignduedate + 4*24*60*60, $instance->duedate); 551 $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id)); 552 $this->assertEquals($assign2duedate + 4*24*60*60, $instance2->duedate); 553 } 554 555 public function test_plugin_settings() { 556 global $DB; 557 558 $now = time(); 559 $this->setUser($this->editingteachers[0]); 560 $assign = $this->create_instance(array('assignsubmission_file_enabled'=>1, 561 'assignsubmission_file_maxfiles'=>12, 562 'assignsubmission_file_maxsizebytes'=>10)); 563 564 $plugin = $assign->get_submission_plugin_by_type('file'); 565 $this->assertEquals('12', $plugin->get_config('maxfilesubmissions')); 566 } 567 568 public function test_update_calendar() { 569 global $DB; 570 571 $this->setUser($this->editingteachers[0]); 572 $userctx = context_user::instance($this->editingteachers[0]->id)->id; 573 574 // Hack to pretend that there was an editor involved. We need both $_POST and $_REQUEST, and a sesskey. 575 $draftid = file_get_unused_draft_itemid(); 576 $_REQUEST['introeditor'] = $draftid; 577 $_POST['introeditor'] = $draftid; 578 $_POST['sesskey'] = sesskey(); 579 580 // Write links to a draft area. 581 $fakearealink1 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">link</a>', 'draftfile.php', $userctx, 582 'user', 'draft', $draftid); 583 $fakearealink2 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">new</a>', 'draftfile.php', $userctx, 584 'user', 'draft', $draftid); 585 586 // Create a new assignment with links to a draft area. 587 $now = time(); 588 $assign = $this->create_instance(array( 589 'duedate' => $now, 590 'intro' => $fakearealink1, 591 'introformat' => FORMAT_HTML 592 )); 593 594 // See if there is an event in the calendar. 595 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id); 596 $event = $DB->get_record('event', $params); 597 $this->assertNotEmpty($event); 598 $this->assertSame('link', $event->description); // The pluginfile links are removed. 599 600 // Make sure the same works when updating the assignment. 601 $instance = $assign->get_instance(); 602 $instance->instance = $instance->id; 603 $instance->intro = $fakearealink2; 604 $instance->introformat = FORMAT_HTML; 605 $assign->update_instance($instance); 606 $params = array('modulename' => 'assign', 'instance' => $assign->get_instance()->id); 607 $event = $DB->get_record('event', $params); 608 $this->assertNotEmpty($event); 609 $this->assertSame('new', $event->description); // The pluginfile links are removed. 610 611 // Create an assignment with a description that should be hidden. 612 $assign = $this->create_instance(array('duedate'=>$now + 160, 613 'alwaysshowdescription'=>false, 614 'allowsubmissionsfromdate'=>$now + 60, 615 'intro'=>'Some text')); 616 617 // Get the event from the calendar. 618 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id); 619 $event = $DB->get_record('event', $params); 620 621 $this->assertEmpty($event->description); 622 623 // Change the allowsubmissionfromdate to the past - do this directly in the DB 624 // because if we call the assignment update method - it will update the calendar 625 // and we want to test that this works from cron. 626 $DB->set_field('assign', 'allowsubmissionsfromdate', $now - 60, array('id'=>$assign->get_instance()->id)); 627 // Run cron to update the event in the calendar. 628 assign::cron(); 629 $event = $DB->get_record('event', $params); 630 631 $this->assertContains('Some text', $event->description); 632 633 } 634 635 public function test_update_instance() { 636 global $DB; 637 638 $this->setUser($this->editingteachers[0]); 639 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1)); 640 641 $now = time(); 642 $instance = $assign->get_instance(); 643 $instance->duedate = $now; 644 $instance->instance = $instance->id; 645 $instance->assignsubmission_onlinetext_enabled = 1; 646 647 $assign->update_instance($instance); 648 649 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id)); 650 $this->assertEquals($now, $instance->duedate); 651 } 652 653 public function test_cannot_submit_empty() { 654 global $PAGE; 655 656 $this->setUser($this->editingteachers[0]); 657 $assign = $this->create_instance(array('submissiondrafts'=>1)); 658 659 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 660 661 // Test you cannot see the submit button for an offline assignment regardless. 662 $this->setUser($this->students[0]); 663 $output = $assign->view_student_summary($this->students[0], true); 664 $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Can submit empty offline assignment'); 665 666 // Test you cannot see the submit button for an online text assignment with no submission. 667 $this->setUser($this->editingteachers[0]); 668 $instance = $assign->get_instance(); 669 $instance->instance = $instance->id; 670 $instance->assignsubmission_onlinetext_enabled = 1; 671 672 $assign->update_instance($instance); 673 $this->setUser($this->students[0]); 674 $output = $assign->view_student_summary($this->students[0], true); 675 $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Cannot submit empty onlinetext assignment'); 676 677 // Simulate a submission. 678 $submission = $assign->get_user_submission($this->students[0]->id, true); 679 $data = new stdClass(); 680 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 681 'text'=>'Submission text', 682 'format'=>FORMAT_MOODLE); 683 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 684 $plugin->save($submission, $data); 685 // Test you can see the submit button for an online text assignment with a submission. 686 $output = $assign->view_student_summary($this->students[0], true); 687 $this->assertContains(get_string('submitassignment', 'assign'), $output, 'Can submit non empty onlinetext assignment'); 688 } 689 690 /** 691 * Test new_submission_empty 692 * 693 * We only test combinations of plugins here. Individual plugins are tested 694 * in their respective test files. 695 * 696 * @dataProvider test_new_submission_empty_testcases 697 * @param string $data The file submission data 698 * @param bool $expected The expected return value 699 */ 700 public function test_new_submission_empty($data, $expected) { 701 $this->resetAfterTest(); 702 $assign = $this->create_instance(['assignsubmission_file_enabled' => 1, 703 'assignsubmission_file_maxfiles' => 12, 704 'assignsubmission_file_maxsizebytes' => 10, 705 'assignsubmission_onlinetext_enabled' => 1]); 706 $this->setUser($this->students[0]); 707 $submission = new stdClass(); 708 709 if ($data['file'] && isset($data['file']['filename'])) { 710 $itemid = file_get_unused_draft_itemid(); 711 $submission->files_filemanager = $itemid; 712 $data['file'] += ['contextid' => context_user::instance($this->students[0]->id)->id, 'itemid' => $itemid]; 713 $fs = get_file_storage(); 714 $fs->create_file_from_string((object)$data['file'], 'Content of ' . $data['file']['filename']); 715 } 716 717 if ($data['onlinetext']) { 718 $submission->onlinetext_editor = ['text' => $data['onlinetext']]; 719 } 720 721 $result = $assign->new_submission_empty($submission); 722 $this->assertTrue($result === $expected); 723 } 724 725 /** 726 * Dataprovider for the test_new_submission_empty testcase 727 * 728 * @return array of testcases 729 */ 730 public function test_new_submission_empty_testcases() { 731 return [ 732 'With file and onlinetext' => [ 733 [ 734 'file' => [ 735 'component' => 'user', 736 'filearea' => 'draft', 737 'filepath' => '/', 738 'filename' => 'not_a_virus.exe' 739 ], 740 'onlinetext' => 'Balin Fundinul Uzbadkhazaddumu' 741 ], 742 false 743 ] 744 ]; 745 } 746 747 public function test_list_participants() { 748 global $CFG, $DB; 749 750 $this->create_extra_users(); 751 $this->setUser($this->editingteachers[0]); 752 $assign = $this->create_instance(array('grade'=>100)); 753 754 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true))); 755 756 // Teacher with user preference set should see suspended users as well. 757 set_user_preference('grade_report_showonlyactiveenrol', false); 758 $assign = $this->create_instance(array('grade'=>100)); 759 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT, 760 count($assign->list_participants(null, true))); 761 762 // Non-editing teacher should not see suspended users, even if user preference is set. 763 $this->setUser($this->teachers[0]); 764 set_user_preference('grade_report_showonlyactiveenrol', false); 765 $assign = $this->create_instance(array('grade'=>100)); 766 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true))); 767 768 // Turn on availability and a group restriction, and check that it doesn't 769 // show users who aren't in the group. 770 $CFG->enableavailability = true; 771 $specialgroup = $this->getDataGenerator()->create_group( 772 array('courseid' => $this->course->id)); 773 $assign = $this->create_instance(array('grade' => 100, 774 'availability' => json_encode(\core_availability\tree::get_root_json( 775 array(\availability_group\condition::get_json($specialgroup->id)))))); 776 groups_add_member($specialgroup, $this->students[0]); 777 groups_add_member($specialgroup, $this->students[1]); 778 $this->assertEquals(2, count($assign->list_participants(null, true))); 779 } 780 781 public function test_get_participant_user_not_exist() { 782 $assign = $this->create_instance(array('grade' => 100)); 783 $this->assertNull($assign->get_participant('-1')); 784 } 785 786 public function test_get_participant_not_enrolled() { 787 $assign = $this->create_instance(array('grade' => 100)); 788 $user = $this->getDataGenerator()->create_user(); 789 $this->assertNull($assign->get_participant($user->id)); 790 } 791 792 public function test_get_participant_no_submission() { 793 $assign = $this->create_instance(array('grade' => 100)); 794 $student = $this->students[0]; 795 $participant = $assign->get_participant($student->id); 796 797 $this->assertEquals($student->id, $participant->id); 798 $this->assertFalse($participant->submitted); 799 $this->assertFalse($participant->requiregrading); 800 } 801 802 public function test_get_participant_with_ungraded_submission() { 803 $assign = $this->create_instance(array('grade' => 100)); 804 $student = $this->students[0]; 805 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 806 807 $this->setUser($student); 808 809 // Simulate a submission. 810 $data = new stdClass(); 811 $data->onlinetext_editor = array( 812 'itemid' => file_get_unused_draft_itemid(), 813 'text' => 'Student submission text', 814 'format' => FORMAT_MOODLE 815 ); 816 817 $notices = array(); 818 $assign->save_submission($data, $notices); 819 820 $data = new stdClass; 821 $data->userid = $student->id; 822 $assign->submit_for_grading($data, array()); 823 824 $participant = $assign->get_participant($student->id); 825 826 $this->assertEquals($student->id, $participant->id); 827 $this->assertTrue($participant->submitted); 828 $this->assertTrue($participant->requiregrading); 829 } 830 831 public function test_get_participant_with_graded_submission() { 832 $assign = $this->create_instance(array('grade' => 100)); 833 $student = $this->students[0]; 834 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 835 836 $this->setUser($student); 837 838 // Simulate a submission. 839 $data = new stdClass(); 840 $data->onlinetext_editor = array( 841 'itemid' => file_get_unused_draft_itemid(), 842 'text' => 'Student submission text', 843 'format' => FORMAT_MOODLE 844 ); 845 846 $notices = array(); 847 $assign->save_submission($data, $notices); 848 849 $data = new stdClass; 850 $data->userid = $student->id; 851 $assign->submit_for_grading($data, array()); 852 853 // This is to make sure the grade happens after the submission because 854 // we have no control over the timemodified values. 855 sleep(1); 856 // Grade the submission. 857 $this->setUser($this->teachers[0]); 858 859 $data = new stdClass(); 860 $data->grade = '50.0'; 861 $assign->testable_apply_grade_to_user($data, $student->id, 0); 862 863 $participant = $assign->get_participant($student->id); 864 865 $this->assertEquals($student->id, $participant->id); 866 $this->assertTrue($participant->submitted); 867 $this->assertFalse($participant->requiregrading); 868 } 869 870 public function test_count_teams() { 871 $this->create_extra_users(); 872 $this->setUser($this->editingteachers[0]); 873 $assign1 = $this->create_instance(array('teamsubmission' => 1)); 874 $this->assertEquals(self::GROUP_COUNT + 1, $assign1->count_teams()); 875 876 $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id)); 877 $this->getDataGenerator()->create_grouping_group(array('groupid' => $this->groups[0]->id, 'groupingid' => $grouping->id)); 878 $this->getDataGenerator()->create_grouping_group(array('groupid' => $this->groups[1]->id, 'groupingid' => $grouping->id)); 879 880 // No active group and non group submissions allowed => 2 groups + the default one. 881 $params = array( 882 'teamsubmission' => 1, 883 'teamsubmissiongroupingid' => $grouping->id, 884 'preventsubmissionnotingroup' => false 885 ); 886 $assign2 = $this->create_instance($params); 887 $this->assertEquals(3, $assign2->count_teams()); 888 889 // An active group => Just the selected one. 890 $this->assertEquals(1, $assign2->count_teams($this->groups[0]->id)); 891 892 // No active group and non group submissions allowed => 2 groups + no default one. 893 $params = array('teamsubmission' => 1, 'teamsubmissiongroupingid' => $grouping->id, 'preventsubmissionnotingroup' => true); 894 $assign3 = $this->create_instance($params); 895 $this->assertEquals(2, $assign3->count_teams()); 896 897 $assign4 = $this->create_instance(array('teamsubmission' => 1, 'preventsubmissionnotingroup' => true)); 898 $this->assertEquals(self::GROUP_COUNT, $assign4->count_teams()); 899 } 900 901 public function test_submit_to_default_group() { 902 global $DB, $SESSION; 903 904 $this->preventResetByRollback(); 905 $sink = $this->redirectMessages(); 906 907 $this->setUser($this->editingteachers[0]); 908 $params = array('teamsubmission' => 1, 909 'assignsubmission_onlinetext_enabled' => 1, 910 'submissiondrafts' => 0, 911 'groupmode' => VISIBLEGROUPS); 912 $assign = $this->create_instance($params); 913 914 $newstudent = $this->getDataGenerator()->create_user(); 915 $studentrole = $DB->get_record('role', array('shortname'=>'student')); 916 $this->getDataGenerator()->enrol_user($newstudent->id, 917 $this->course->id, 918 $studentrole->id); 919 $this->setUser($newstudent); 920 $data = new stdClass(); 921 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 922 'text'=>'Submission text', 923 'format'=>FORMAT_MOODLE); 924 $notices = array(); 925 926 $group = $assign->get_submission_group($newstudent->id); 927 $this->assertFalse($group, 'New student is in default group'); 928 $assign->save_submission($data, $notices); 929 $this->assertEmpty($notices, 'No errors on save submission'); 930 931 // Set active groups to all groups. 932 $this->setUser($this->teachers[0]); 933 $SESSION->activegroup[$this->course->id]['aag'][0] = 0; 934 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED)); 935 936 // Set an active group. 937 $anothergroup = $this->groups[0]; 938 $SESSION->activegroup[$this->course->id]['aag'][0] = (int)$anothergroup->id; 939 $this->assertEquals(0, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED)); 940 941 $sink->close(); 942 } 943 944 public function test_count_submissions() { 945 global $SESSION; 946 947 $this->create_extra_users(); 948 $this->setUser($this->editingteachers[0]); 949 $assign1 = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1)); 950 951 // Simulate a submission. 952 $this->setUser($this->extrastudents[0]); 953 $submission = $assign1->get_user_submission($this->extrastudents[0]->id, true); 954 $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT; 955 $assign1->testable_update_submission($submission, $this->extrastudents[0]->id, true, false); 956 // Leave this one as DRAFT. 957 $data = new stdClass(); 958 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 959 'text'=>'Submission text', 960 'format'=>FORMAT_MOODLE); 961 $plugin = $assign1->get_submission_plugin_by_type('onlinetext'); 962 $plugin->save($submission, $data); 963 964 // Simulate adding a grade. 965 $this->setUser($this->teachers[0]); 966 $data = new stdClass(); 967 $data->grade = '50.0'; 968 $assign1->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0); 969 970 // Simulate a submission. 971 $this->setUser($this->extrastudents[1]); 972 $submission = $assign1->get_user_submission($this->extrastudents[1]->id, true); 973 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 974 $assign1->testable_update_submission($submission, $this->extrastudents[1]->id, true, false); 975 $data = new stdClass(); 976 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 977 'text'=>'Submission text', 978 'format'=>FORMAT_MOODLE); 979 $plugin = $assign1->get_submission_plugin_by_type('onlinetext'); 980 $plugin->save($submission, $data); 981 982 // Simulate a submission. 983 $this->setUser($this->extrastudents[2]); 984 $submission = $assign1->get_user_submission($this->extrastudents[2]->id, true); 985 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 986 $assign1->testable_update_submission($submission, $this->extrastudents[2]->id, true, false); 987 $data = new stdClass(); 988 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 989 'text'=>'Submission text', 990 'format'=>FORMAT_MOODLE); 991 $plugin = $assign1->get_submission_plugin_by_type('onlinetext'); 992 $plugin->save($submission, $data); 993 994 // Simulate a submission. 995 $this->setUser($this->extrastudents[3]); 996 $submission = $assign1->get_user_submission($this->extrastudents[3]->id, true); 997 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 998 $assign1->testable_update_submission($submission, $this->extrastudents[3]->id, true, false); 999 $data = new stdClass(); 1000 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 1001 'text'=>'Submission text', 1002 'format'=>FORMAT_MOODLE); 1003 $plugin = $assign1->get_submission_plugin_by_type('onlinetext'); 1004 $plugin->save($submission, $data); 1005 1006 // Simulate a submission for suspended user, this will never be counted. 1007 $this->setUser($this->extrastudents[3]); 1008 $submission = $assign1->get_user_submission($this->extrasuspendedstudents[0]->id, true); 1009 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1010 $assign1->testable_update_submission($submission, $this->extrasuspendedstudents[0]->id, true, false); 1011 $data = new stdClass(); 1012 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 1013 'text'=>'Submission text', 1014 'format'=>FORMAT_MOODLE); 1015 $plugin = $assign1->get_submission_plugin_by_type('onlinetext'); 1016 $plugin->save($submission, $data); 1017 1018 // Wait 1 second so the submission and grade do not have the same timemodified. 1019 sleep(1); 1020 // Simulate adding a grade. 1021 $this->setUser($this->editingteachers[0]); 1022 $data = new stdClass(); 1023 $data->grade = '50.0'; 1024 $assign1->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0); 1025 $assign1->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0); 1026 1027 // Create a new submission with status NEW. 1028 $this->setUser($this->extrastudents[4]); 1029 $submission = $assign1->get_user_submission($this->extrastudents[4]->id, true); 1030 1031 $this->assertEquals(2, $assign1->count_grades()); 1032 $this->assertEquals(4, $assign1->count_submissions()); 1033 $this->assertEquals(5, $assign1->count_submissions(true)); 1034 $this->assertEquals(2, $assign1->count_submissions_need_grading()); 1035 $this->assertEquals(3, $assign1->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED)); 1036 $this->assertEquals(1, $assign1->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT)); 1037 1038 // Groups. 1039 $assign2 = $this->create_instance(array( 1040 'assignsubmission_onlinetext_enabled' => 1, 1041 'groupmode' => VISIBLEGROUPS 1042 )); 1043 1044 $this->setUser($this->extrastudents[1]); 1045 $submission = $assign2->get_user_submission($this->extrastudents[1]->id, true); 1046 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1047 $assign2->testable_update_submission($submission, $this->extrastudents[1]->id, true, false); 1048 $data = new stdClass(); 1049 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1050 'text' => 'Submission text', 1051 'format' => FORMAT_MOODLE); 1052 $plugin = $assign2->get_submission_plugin_by_type('onlinetext'); 1053 $plugin->save($submission, $data); 1054 1055 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED)); 1056 1057 // Set active groups to all groups. 1058 $this->setUser($this->teachers[0]); 1059 $SESSION->activegroup[$this->course->id]['aag'][0] = 0; 1060 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED)); 1061 1062 // Set the user group. 1063 $studentgroups = groups_get_user_groups($this->course->id, $this->extrastudents[1]->id); 1064 $this->assertEquals(1, count($studentgroups)); 1065 $studentgroup = array_pop($studentgroups); 1066 $SESSION->activegroup[$this->course->id]['aag'][0] = $studentgroup[0]; 1067 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED)); 1068 1069 // Set another group. 1070 $anothergroup = $this->groups[0]; 1071 $this->assertNotEquals($anothergroup->id, $studentgroup[0]); 1072 $SESSION->activegroup[$this->course->id]['aag'][0] = (int)$anothergroup->id; 1073 $this->assertEquals(0, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED)); 1074 } 1075 1076 public function test_count_submissions_for_groups() { 1077 $this->create_extra_users(); 1078 $groupid = null; 1079 $this->setUser($this->editingteachers[0]); 1080 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1, 'teamsubmission' => 1)); 1081 1082 // Simulate a submission. 1083 $this->setUser($this->extrastudents[0]); 1084 $submission = $assign->get_group_submission($this->extrastudents[0]->id, $groupid, true); 1085 $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT; 1086 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false); 1087 // Leave this one as DRAFT. 1088 $data = new stdClass(); 1089 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1090 'text' => 'Submission text', 1091 'format' => FORMAT_MOODLE); 1092 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 1093 $plugin->save($submission, $data); 1094 1095 // Simulate adding a grade. 1096 $this->setUser($this->teachers[0]); 1097 $data = new stdClass(); 1098 $data->grade = '50.0'; 1099 $assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0); 1100 1101 // Simulate a submission. 1102 $this->setUser($this->extrastudents[1]); 1103 $submission = $assign->get_group_submission($this->extrastudents[1]->id, $groupid, true); 1104 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1105 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, false); 1106 $data = new stdClass(); 1107 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1108 'text' => 'Submission text', 1109 'format' => FORMAT_MOODLE); 1110 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 1111 $plugin->save($submission, $data); 1112 1113 // Simulate a submission. 1114 $this->setUser($this->extrastudents[2]); 1115 $submission = $assign->get_group_submission($this->extrastudents[2]->id, $groupid, true); 1116 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1117 $assign->testable_update_submission($submission, $this->extrastudents[2]->id, true, false); 1118 $data = new stdClass(); 1119 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1120 'text' => 'Submission text', 1121 'format' => FORMAT_MOODLE); 1122 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 1123 $plugin->save($submission, $data); 1124 1125 // Simulate a submission. 1126 $this->setUser($this->extrastudents[3]); 1127 $submission = $assign->get_group_submission($this->extrastudents[3]->id, $groupid, true); 1128 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1129 $assign->testable_update_submission($submission, $this->extrastudents[3]->id, true, false); 1130 $data = new stdClass(); 1131 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1132 'text' => 'Submission text', 1133 'format' => FORMAT_MOODLE); 1134 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 1135 $plugin->save($submission, $data); 1136 1137 // Simulate adding a grade. 1138 $this->setUser($this->editingteachers[0]); 1139 $data = new stdClass(); 1140 $data->grade = '50.0'; 1141 $assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0); 1142 $assign->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0); 1143 1144 // Create a new submission with status NEW. 1145 $this->setUser($this->extrastudents[4]); 1146 $submission = $assign->get_group_submission($this->extrastudents[4]->id, $groupid, true); 1147 1148 $this->assertEquals(2, $assign->count_grades()); 1149 $this->assertEquals(4, $assign->count_submissions()); 1150 $this->assertEquals(5, $assign->count_submissions(true)); 1151 $this->assertEquals(3, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED)); 1152 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT)); 1153 } 1154 1155 public function test_get_grading_userid_list() { 1156 $this->create_extra_users(); 1157 $this->setUser($this->editingteachers[0]); 1158 $assign = $this->create_instance(); 1159 1160 $users = $assign->testable_get_grading_userid_list(); 1161 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($users)); 1162 1163 $this->setUser($this->editingteachers[0]); 1164 set_user_preference('grade_report_showonlyactiveenrol', false); 1165 $assign = $this->create_instance(); 1166 1167 $users = $assign->testable_get_grading_userid_list(); 1168 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT, count($users)); 1169 } 1170 1171 public function test_cron() { 1172 // First run cron so there are no messages waiting to be sent (from other tests). 1173 cron_setup_user(); 1174 assign::cron(); 1175 1176 // Now create an assignment and add some feedback. 1177 $this->setUser($this->editingteachers[0]); 1178 $assign = $this->create_instance(array('sendstudentnotifications'=>1)); 1179 1180 // Simulate adding a grade. 1181 $this->setUser($this->teachers[0]); 1182 $data = new stdClass(); 1183 $data->grade = '50.0'; 1184 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 1185 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0); 1186 1187 $data->sendstudentnotifications = false; 1188 $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0); 1189 1190 // Now run cron and see that one message was sent. 1191 $this->preventResetByRollback(); 1192 $sink = $this->redirectMessages(); 1193 cron_setup_user(); 1194 $this->expectOutputRegex('/Done processing 2 assignment submissions/'); 1195 assign::cron(); 1196 1197 $messages = $sink->get_messages(); 1198 // The sent count should be 2, because the 3rd one was marked as do not send notifications. 1199 $this->assertEquals(2, count($messages)); 1200 $this->assertEquals(1, $messages[0]->notification); 1201 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname); 1202 1203 // Regrading a grade causes a notification to the user. 1204 $data->sendstudentnotifications = true; 1205 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 1206 assign::cron(); 1207 $messages = $sink->get_messages(); 1208 $this->assertEquals(3, count($messages)); 1209 } 1210 1211 /** 1212 * Test delivery of grade notifications as controlled by marking workflow. 1213 */ 1214 public function test_markingworkflow_cron() { 1215 // First run cron so there are no messages waiting to be sent (from other tests). 1216 cron_setup_user(); 1217 assign::cron(); 1218 1219 // Now create an assignment with marking workflow enabled. 1220 $this->setUser($this->editingteachers[0]); 1221 $assign = $this->create_instance(array('sendstudentnotifications' => 1, 'markingworkflow' => 1)); 1222 1223 // Simulate adding a grade. 1224 $this->setUser($this->teachers[0]); 1225 $data = new stdClass(); 1226 $data->grade = '50.0'; 1227 1228 // This student will not receive notification. 1229 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE; 1230 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 1231 1232 // This student will receive notification. 1233 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED; 1234 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0); 1235 1236 // Now run cron and see that one message was sent. 1237 $this->preventResetByRollback(); 1238 $sink = $this->redirectMessages(); 1239 cron_setup_user(); 1240 $this->expectOutputRegex('/Done processing 1 assignment submissions/'); 1241 assign::cron(); 1242 1243 $messages = $sink->get_messages(); 1244 $this->assertEquals(1, count($messages)); 1245 $this->assertEquals($messages[0]->useridto, $this->students[1]->id); 1246 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname); 1247 } 1248 1249 public function test_is_graded() { 1250 $this->setUser($this->editingteachers[0]); 1251 $assign = $this->create_instance(); 1252 1253 // Simulate adding a grade. 1254 $this->setUser($this->teachers[0]); 1255 $data = new stdClass(); 1256 $data->grade = '50.0'; 1257 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 1258 1259 $this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id)); 1260 $this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id)); 1261 } 1262 1263 public function test_can_grade() { 1264 global $DB; 1265 1266 $this->setUser($this->editingteachers[0]); 1267 $assign = $this->create_instance(); 1268 1269 $this->setUser($this->students[0]); 1270 $this->assertEquals(false, $assign->can_grade()); 1271 $this->setUser($this->editingteachers[0]); 1272 $this->assertEquals(true, $assign->can_grade()); 1273 $this->setUser($this->teachers[0]); 1274 $this->assertEquals(true, $assign->can_grade()); 1275 1276 // Test the viewgrades capability - without mod/assign:grade. 1277 $this->setUser($this->students[0]); 1278 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1279 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id); 1280 $this->assertEquals(false, $assign->can_grade()); 1281 } 1282 1283 public function test_can_view_submission() { 1284 global $DB; 1285 1286 $this->create_extra_users(); 1287 $this->setUser($this->editingteachers[0]); 1288 $assign = $this->create_instance(); 1289 1290 $this->setUser($this->students[0]); 1291 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id)); 1292 $this->assertEquals(false, $assign->can_view_submission($this->students[1]->id)); 1293 $this->assertEquals(false, $assign->can_view_submission($this->teachers[0]->id)); 1294 $this->setUser($this->teachers[0]); 1295 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id)); 1296 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id)); 1297 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id)); 1298 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id)); 1299 $this->setUser($this->editingteachers[0]); 1300 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id)); 1301 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id)); 1302 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id)); 1303 $this->assertEquals(true, $assign->can_view_submission($this->extrasuspendedstudents[0]->id)); 1304 1305 // Test the viewgrades capability - without mod/assign:grade. 1306 $this->setUser($this->students[0]); 1307 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1308 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id); 1309 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id)); 1310 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id)); 1311 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id)); 1312 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id)); 1313 } 1314 1315 1316 public function test_update_submission() { 1317 $this->create_extra_users(); 1318 $this->setUser($this->editingteachers[0]); 1319 $assign = $this->create_instance(); 1320 1321 $this->setUser($this->extrastudents[0]); 1322 $now = time(); 1323 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true); 1324 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false); 1325 1326 $this->setUser($this->teachers[0]); 1327 // Verify the gradebook update. 1328 $gradinginfo = grade_get_grades($this->course->id, 1329 'mod', 1330 'assign', 1331 $assign->get_instance()->id, 1332 $this->extrastudents[0]->id); 1333 1334 $this->assertEquals($this->extrastudents[0]->id, 1335 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified); 1336 1337 // Now verify group assignments. 1338 $this->setUser($this->editingteachers[0]); 1339 $assign = $this->create_instance(array('teamsubmission'=>1)); 1340 1341 $this->setUser($this->extrastudents[0]); 1342 $now = time(); 1343 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true); 1344 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true); 1345 1346 // Check that at least 2 active members and 1 suspended member of the submission group had their submission updated. 1347 1348 $this->setUser($this->editingteachers[0]); 1349 $gradinginfo = grade_get_grades($this->course->id, 1350 'mod', 1351 'assign', 1352 $assign->get_instance()->id, 1353 $this->extrastudents[0]->id); 1354 1355 $this->assertEquals($this->extrastudents[0]->id, 1356 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified); 1357 1358 $gradinginfo = grade_get_grades($this->course->id, 1359 'mod', 1360 'assign', 1361 $assign->get_instance()->id, 1362 $this->extrastudents[self::GROUP_COUNT]->id); 1363 1364 $this->assertEquals($this->extrastudents[self::GROUP_COUNT]->id, 1365 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT]->id]->usermodified); 1366 1367 $gradinginfo = grade_get_grades($this->course->id, 1368 'mod', 1369 'assign', 1370 $assign->get_instance()->id, 1371 $this->extrasuspendedstudents[0]->id); 1372 $this->assertEquals($this->extrasuspendedstudents[0]->id, 1373 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[0]->id]->usermodified); 1374 1375 // Check the same with non-editing teacher and make sure submission is not updated for suspended user. 1376 $this->setUser($this->editingteachers[0]); 1377 $assign = $this->create_instance(array('teamsubmission'=>1)); 1378 1379 $this->setUser($this->extrastudents[1]); 1380 $now = time(); 1381 $submission = $assign->get_group_submission($this->extrastudents[1]->id, 0, true); 1382 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, true); 1383 1384 $this->setUser($this->teachers[0]); 1385 $gradinginfo = grade_get_grades($this->course->id, 1386 'mod', 1387 'assign', 1388 $assign->get_instance()->id, 1389 $this->extrastudents[1]->id); 1390 1391 $this->assertEquals($this->extrastudents[1]->id, 1392 $gradinginfo->items[0]->grades[$this->extrastudents[1]->id]->usermodified); 1393 1394 $gradinginfo = grade_get_grades($this->course->id, 1395 'mod', 1396 'assign', 1397 $assign->get_instance()->id, 1398 $this->extrastudents[self::GROUP_COUNT+1]->id); 1399 1400 $this->assertEquals($this->extrastudents[self::GROUP_COUNT+1]->id, 1401 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT+1]->id]->usermodified); 1402 1403 $gradinginfo = grade_get_grades($this->course->id, 1404 'mod', 1405 'assign', 1406 $assign->get_instance()->id, 1407 $this->extrasuspendedstudents[1]->id); 1408 $this->assertEquals($this->extrasuspendedstudents[1]->id, 1409 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[1]->id]->usermodified); 1410 1411 // Now verify blind marking. 1412 $this->setUser($this->editingteachers[0]); 1413 $assign = $this->create_instance(array('blindmarking'=>1)); 1414 1415 $this->setUser($this->extrastudents[0]); 1416 $now = time(); 1417 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true); 1418 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false); 1419 1420 $this->setUser($this->editingteachers[0]); 1421 $gradinginfo = grade_get_grades($this->course->id, 1422 'mod', 1423 'assign', 1424 $assign->get_instance()->id, 1425 $this->extrastudents[0]->id); 1426 1427 $this->assertEquals(null, $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->datesubmitted); 1428 } 1429 1430 public function test_group_submissions_submit_for_marking_requireallteammemberssubmit() { 1431 global $PAGE; 1432 1433 $this->create_extra_users(); 1434 // Now verify group assignments. 1435 $this->setUser($this->editingteachers[0]); 1436 $assign = $this->create_instance(array('teamsubmission'=>1, 1437 'assignsubmission_onlinetext_enabled'=>1, 1438 'submissiondrafts'=>1, 1439 'requireallteammemberssubmit'=>1)); 1440 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 1441 1442 // Add a submission. 1443 $this->setUser($this->extrastudents[0]); 1444 $data = new stdClass(); 1445 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 1446 'text'=>'Submission text', 1447 'format'=>FORMAT_MOODLE); 1448 1449 $notices = array(); 1450 $assign->save_submission($data, $notices); 1451 1452 // Check we can see the submit button. 1453 $output = $assign->view_student_summary($this->extrastudents[0], true); 1454 $this->assertContains(get_string('submitassignment', 'assign'), $output); 1455 1456 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true); 1457 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1458 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true); 1459 1460 // Check that the student does not see "Submit" button. 1461 $output = $assign->view_student_summary($this->extrastudents[0], true); 1462 $this->assertNotContains(get_string('submitassignment', 'assign'), $output); 1463 1464 // Change to another user in the same group. 1465 $this->setUser($this->extrastudents[self::GROUP_COUNT]); 1466 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true); 1467 $this->assertContains(get_string('submitassignment', 'assign'), $output); 1468 1469 $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true); 1470 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1471 $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true); 1472 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true); 1473 $this->assertNotContains(get_string('submitassignment', 'assign'), $output); 1474 } 1475 1476 public function test_group_submissions_submit_for_marking() { 1477 global $PAGE; 1478 1479 $this->create_extra_users(); 1480 // Now verify group assignments. 1481 $this->setUser($this->editingteachers[0]); 1482 $time = time(); 1483 $assign = $this->create_instance(array('teamsubmission'=>1, 1484 'assignsubmission_onlinetext_enabled'=>1, 1485 'submissiondrafts'=>1, 1486 'requireallteammemberssubmit'=>0, 1487 'duedate' => $time - 2*24*60*60)); 1488 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 1489 1490 $this->setUser($this->extrastudents[0]); 1491 // Add a submission. 1492 $data = new stdClass(); 1493 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 1494 'text'=>'Submission text', 1495 'format'=>FORMAT_MOODLE); 1496 1497 $notices = array(); 1498 $assign->save_submission($data, $notices); 1499 1500 // Check we can see the submit button. 1501 $output = $assign->view_student_summary($this->extrastudents[0], true); 1502 $this->assertContains(get_string('submitassignment', 'assign'), $output); 1503 $this->assertContains(get_string('timeremaining', 'assign'), $output); 1504 $difftime = time() - $time; 1505 $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60 + $difftime)), $output); 1506 1507 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true); 1508 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1509 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true); 1510 1511 // Check that the student does not see "Submit" button. 1512 $output = $assign->view_student_summary($this->extrastudents[0], true); 1513 $this->assertNotContains(get_string('submitassignment', 'assign'), $output); 1514 1515 // Change to another user in the same group. 1516 $this->setUser($this->extrastudents[self::GROUP_COUNT]); 1517 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true); 1518 $this->assertNotContains(get_string('submitassignment', 'assign'), $output); 1519 1520 // Check that time remaining is not overdue. 1521 $this->assertContains(get_string('timeremaining', 'assign'), $output); 1522 $difftime = time() - $time; 1523 $this->assertContains(get_string('submittedlate', 'assign', format_time(2*24*60*60 + $difftime)), $output); 1524 1525 $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true); 1526 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1527 $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true); 1528 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true); 1529 $this->assertNotContains(get_string('submitassignment', 'assign'), $output); 1530 } 1531 1532 public function test_submissions_open() { 1533 $this->setUser($this->editingteachers[0]); 1534 1535 $now = time(); 1536 $tomorrow = $now + 24*60*60; 1537 $oneweek = $now + 7*24*60*60; 1538 $yesterday = $now - 24*60*60; 1539 1540 $assign = $this->create_instance(); 1541 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id)); 1542 1543 $assign = $this->create_instance(array('duedate'=>$tomorrow)); 1544 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id)); 1545 1546 $assign = $this->create_instance(array('duedate'=>$yesterday)); 1547 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id)); 1548 1549 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$tomorrow)); 1550 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id)); 1551 1552 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$yesterday)); 1553 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id)); 1554 1555 $assign->testable_save_user_extension($this->students[0]->id, $tomorrow); 1556 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id)); 1557 1558 $assign = $this->create_instance(array('submissiondrafts'=>1)); 1559 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id)); 1560 1561 $this->setUser($this->students[0]); 1562 $now = time(); 1563 $submission = $assign->get_user_submission($this->students[0]->id, true); 1564 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1565 $assign->testable_update_submission($submission, $this->students[0]->id, true, false); 1566 $this->setUser($this->editingteachers[0]); 1567 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id)); 1568 } 1569 1570 public function test_get_graders() { 1571 $this->create_extra_users(); 1572 $this->setUser($this->editingteachers[0]); 1573 1574 // Create an assignment with no groups. 1575 $assign = $this->create_instance(); 1576 $this->assertCount(self::DEFAULT_TEACHER_COUNT + 1577 self::DEFAULT_EDITING_TEACHER_COUNT + 1578 self::EXTRA_TEACHER_COUNT + 1579 self::EXTRA_EDITING_TEACHER_COUNT, 1580 $assign->testable_get_graders($this->students[0]->id)); 1581 1582 // Force create an assignment with SEPARATEGROUPS. 1583 $data = new stdClass(); 1584 $data->courseid = $this->course->id; 1585 $data->name = 'Grouping'; 1586 $groupingid = groups_create_grouping($data); 1587 groups_assign_grouping($groupingid, $this->groups[0]->id); 1588 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS)); 1589 1590 $this->setUser($this->students[1]); 1591 $this->assertCount(4, $assign->testable_get_graders($this->students[0]->id)); 1592 // Note the second student is in a group that is not in the grouping. 1593 // This means that we get all graders that are not in a group in the grouping. 1594 $this->assertCount(10, $assign->testable_get_graders($this->students[1]->id)); 1595 } 1596 1597 public function test_get_notified_users() { 1598 global $CFG, $DB; 1599 1600 $capability = 'mod/assign:receivegradernotifications'; 1601 $coursecontext = context_course::instance($this->course->id); 1602 $role = $DB->get_record('role', array('shortname' => 'teacher')); 1603 1604 $this->create_extra_users(); 1605 $this->setUser($this->editingteachers[0]); 1606 1607 // Create an assignment with no groups. 1608 $assign = $this->create_instance(); 1609 1610 $this->assertCount(self::DEFAULT_TEACHER_COUNT + 1611 self::DEFAULT_EDITING_TEACHER_COUNT + 1612 self::EXTRA_TEACHER_COUNT + 1613 self::EXTRA_EDITING_TEACHER_COUNT, 1614 $assign->testable_get_notifiable_users($this->students[0]->id)); 1615 1616 // Change nonediting teachers role to not receive grader notifications. 1617 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext); 1618 1619 $this->assertCount(self::DEFAULT_EDITING_TEACHER_COUNT + 1620 self::EXTRA_EDITING_TEACHER_COUNT, 1621 $assign->testable_get_notifiable_users($this->students[0]->id)); 1622 1623 // Reset nonediting teachers role to default. 1624 unassign_capability($capability, $role->id, $coursecontext); 1625 1626 // Force create an assignment with SEPARATEGROUPS. 1627 $data = new stdClass(); 1628 $data->courseid = $this->course->id; 1629 $data->name = 'Grouping'; 1630 $groupingid = groups_create_grouping($data); 1631 groups_assign_grouping($groupingid, $this->groups[0]->id); 1632 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS)); 1633 1634 $this->setUser($this->students[1]); 1635 $this->assertCount(4, $assign->testable_get_notifiable_users($this->students[0]->id)); 1636 // Note the second student is in a group that is not in the grouping. 1637 // This means that we get all graders that are not in a group in the grouping. 1638 $this->assertCount(10, $assign->testable_get_notifiable_users($this->students[1]->id)); 1639 1640 // Change nonediting teachers role to not receive grader notifications. 1641 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext); 1642 1643 $this->assertCount(2, $assign->testable_get_notifiable_users($this->students[0]->id)); 1644 // Note the second student is in a group that is not in the grouping. 1645 // This means that we get all graders that are not in a group in the grouping. 1646 $this->assertCount(5, $assign->testable_get_notifiable_users($this->students[1]->id)); 1647 } 1648 1649 public function test_group_members_only() { 1650 global $CFG; 1651 1652 $this->setAdminUser(); 1653 $this->create_extra_users(); 1654 $CFG->enableavailability = true; 1655 $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id)); 1656 groups_assign_grouping($grouping->id, $this->groups[0]->id); 1657 1658 // Force create an assignment with SEPARATEGROUPS. 1659 $instance = $this->getDataGenerator()->create_module('assign', array('course'=>$this->course->id), 1660 array('availability' => json_encode(\core_availability\tree::get_root_json(array( 1661 \availability_grouping\condition::get_json()))), 1662 'groupingid' => $grouping->id)); 1663 1664 $cm = get_coursemodule_from_instance('assign', $instance->id); 1665 $context = context_module::instance($cm->id); 1666 $assign = new testable_assign($context, $cm, $this->course); 1667 1668 $this->setUser($this->teachers[0]); 1669 get_fast_modinfo($this->course, 0, true); 1670 $this->assertCount(5, $assign->list_participants(0, true)); 1671 1672 } 1673 1674 public function test_get_uniqueid_for_user() { 1675 $this->setUser($this->editingteachers[0]); 1676 $assign = $this->create_instance(); 1677 1678 foreach ($this->students as $student) { 1679 $uniqueid = $assign->get_uniqueid_for_user($student->id); 1680 $this->assertEquals($student->id, $assign->get_user_id_for_uniqueid($uniqueid)); 1681 } 1682 } 1683 1684 public function test_show_student_summary() { 1685 global $CFG, $PAGE; 1686 1687 $this->setUser($this->editingteachers[0]); 1688 $assign = $this->create_instance(); 1689 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 1690 1691 // No feedback should be available because this student has not been graded. 1692 $this->setUser($this->students[0]); 1693 $output = $assign->view_student_summary($this->students[0], true); 1694 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if there is no grade'); 1695 // Simulate adding a grade. 1696 $this->setUser($this->teachers[0]); 1697 $data = new stdClass(); 1698 $data->grade = '50.0'; 1699 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 1700 1701 // Now we should see the feedback. 1702 $this->setUser($this->students[0]); 1703 $output = $assign->view_student_summary($this->students[0], true); 1704 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback if there is a grade'); 1705 1706 // Now hide the grade in gradebook. 1707 $this->setUser($this->teachers[0]); 1708 require_once($CFG->libdir.'/gradelib.php'); 1709 $gradeitem = new grade_item(array( 1710 'itemtype' => 'mod', 1711 'itemmodule' => 'assign', 1712 'iteminstance' => $assign->get_instance()->id, 1713 'courseid' => $this->course->id)); 1714 1715 $gradeitem->set_hidden(1, false); 1716 1717 // No feedback should be available because the grade is hidden. 1718 $this->setUser($this->students[0]); 1719 $output = $assign->view_student_summary($this->students[0], true); 1720 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook'); 1721 1722 // Do the same but add feedback. 1723 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1)); 1724 1725 $this->setUser($this->teachers[0]); 1726 $grade = $assign->get_user_grade($this->students[0]->id, true); 1727 $data = new stdClass(); 1728 $data->assignfeedbackcomments_editor = array('text'=>'Tomato sauce', 1729 'format'=>FORMAT_MOODLE); 1730 $plugin = $assign->get_feedback_plugin_by_type('comments'); 1731 $plugin->save($grade, $data); 1732 1733 // Should have feedback but no grade. 1734 $this->setUser($this->students[0]); 1735 $output = $assign->view_student_summary($this->students[0], true); 1736 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback even if there is no grade'); 1737 $this->assertEquals(false, strpos($output, 'Grade'), 'Do not show grade when there is no grade.'); 1738 $this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.'); 1739 1740 // Now hide the grade in gradebook. 1741 $this->setUser($this->teachers[0]); 1742 $gradeitem = new grade_item(array( 1743 'itemtype' => 'mod', 1744 'itemmodule' => 'assign', 1745 'iteminstance' => $assign->get_instance()->id, 1746 'courseid' => $this->course->id)); 1747 1748 $gradeitem->set_hidden(1, false); 1749 1750 // No feedback should be available because the grade is hidden. 1751 $this->setUser($this->students[0]); 1752 $output = $assign->view_student_summary($this->students[0], true); 1753 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook'); 1754 } 1755 1756 public function test_attempt_reopen_method_manual() { 1757 global $PAGE; 1758 1759 $this->setUser($this->editingteachers[0]); 1760 $assign = $this->create_instance(array('attemptreopenmethod'=>ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL, 1761 'maxattempts'=>3, 1762 'submissiondrafts'=>1, 1763 'assignsubmission_onlinetext_enabled'=>1)); 1764 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 1765 1766 // Student should be able to see an add submission button. 1767 $this->setUser($this->students[0]); 1768 $output = $assign->view_student_summary($this->students[0], true); 1769 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign'))); 1770 1771 // Add a submission. 1772 $now = time(); 1773 $submission = $assign->get_user_submission($this->students[0]->id, true); 1774 $data = new stdClass(); 1775 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 1776 'text'=>'Submission text', 1777 'format'=>FORMAT_MOODLE); 1778 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 1779 $plugin->save($submission, $data); 1780 1781 // And now submit it for marking. 1782 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1783 $assign->testable_update_submission($submission, $this->students[0]->id, true, false); 1784 1785 // Verify the student cannot make changes to the submission. 1786 $output = $assign->view_student_summary($this->students[0], true); 1787 $this->assertEquals(false, strpos($output, get_string('addsubmission', 'assign'))); 1788 1789 // Mark the submission. 1790 $this->setUser($this->teachers[0]); 1791 $data = new stdClass(); 1792 $data->grade = '50.0'; 1793 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 1794 1795 // Check the student can see the grade. 1796 $this->setUser($this->students[0]); 1797 $output = $assign->view_student_summary($this->students[0], true); 1798 $this->assertNotEquals(false, strpos($output, '50.0')); 1799 1800 // Allow the student another attempt. 1801 $this->teachers[0]->ignoresesskey = true; 1802 $this->setUser($this->teachers[0]); 1803 $result = $assign->testable_process_add_attempt($this->students[0]->id); 1804 $this->assertEquals(true, $result); 1805 1806 // Check that the previous attempt is now in the submission history table. 1807 $this->setUser($this->students[0]); 1808 $output = $assign->view_student_summary($this->students[0], true); 1809 // Need a better check. 1810 $this->assertNotEquals(false, strpos($output, 'Submission text'), 'Contains: Submission text'); 1811 1812 // Check that the student now has a button for Add a new attempt". 1813 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign'))); 1814 // Check that the student now does not have a button for Submit. 1815 $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign'))); 1816 1817 // Check that the student now has a submission history. 1818 $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign'))); 1819 1820 $this->setUser($this->teachers[0]); 1821 // Check that the grading table loads correctly and contains this user. 1822 // This is also testing that we do not get duplicate rows in the grading table. 1823 $gradingtable = new assign_grading_table($assign, 100, '', 0, true); 1824 $output = $assign->get_renderer()->render($gradingtable); 1825 $this->assertEquals(true, strpos($output, $this->students[0]->lastname)); 1826 1827 // Should be 1 not 2. 1828 $this->assertEquals(1, $assign->count_submissions()); 1829 $this->assertEquals(1, $assign->count_submissions_with_status('reopened')); 1830 $this->assertEquals(0, $assign->count_submissions_need_grading()); 1831 $this->assertEquals(1, $assign->count_grades()); 1832 1833 // Change max attempts to unlimited. 1834 $formdata = clone($assign->get_instance()); 1835 $formdata->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS; 1836 $formdata->instance = $formdata->id; 1837 $assign->update_instance($formdata); 1838 1839 // Mark the submission again. 1840 $data = new stdClass(); 1841 $data->grade = '60.0'; 1842 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1); 1843 1844 // Check the grade exists. 1845 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id); 1846 $this->assertEquals(60, (int)$grades[$this->students[0]->id]->rawgrade); 1847 1848 // Check we can reopen still. 1849 $result = $assign->testable_process_add_attempt($this->students[0]->id); 1850 $this->assertEquals(true, $result); 1851 1852 // Should no longer have a grade because there is no grade for the latest attempt. 1853 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id); 1854 $this->assertEmpty($grades); 1855 1856 } 1857 1858 /** 1859 * Test reopen behavior when in "Reopen until pass" mode. 1860 */ 1861 public function test_attempt_reopen_method_untilpass() { 1862 global $PAGE; 1863 1864 $this->setUser($this->editingteachers[0]); 1865 $assign = $this->create_instance(array('attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS, 1866 'maxattempts' => 3, 1867 'submissiondrafts' => 1, 1868 'assignsubmission_onlinetext_enabled' => 1)); 1869 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 1870 1871 // Set grade to pass to 80. 1872 $gradeitem = $assign->get_grade_item(); 1873 $gradeitem->gradepass = '80.0'; 1874 $gradeitem->update(); 1875 1876 // Student should be able to see an add submission button. 1877 $this->setUser($this->students[0]); 1878 $output = $assign->view_student_summary($this->students[0], true); 1879 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign'))); 1880 1881 // Add a submission. 1882 $now = time(); 1883 $submission = $assign->get_user_submission($this->students[0]->id, true); 1884 $data = new stdClass(); 1885 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1886 'text' => 'Submission text', 1887 'format' => FORMAT_MOODLE); 1888 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 1889 $plugin->save($submission, $data); 1890 1891 // And now submit it for marking. 1892 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1893 $assign->testable_update_submission($submission, $this->students[0]->id, true, false); 1894 1895 // Verify the student cannot make a new attempt. 1896 $output = $assign->view_student_summary($this->students[0], true); 1897 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign'))); 1898 1899 // Mark the submission as non-passing. 1900 $this->setUser($this->teachers[0]); 1901 $data = new stdClass(); 1902 $data->grade = '50.0'; 1903 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 1904 1905 // Check the student can see the grade. 1906 $this->setUser($this->students[0]); 1907 $output = $assign->view_student_summary($this->students[0], true); 1908 $this->assertNotEquals(false, strpos($output, '50.0')); 1909 1910 // Check that the student now has a button for Add a new attempt. 1911 $output = $assign->view_student_summary($this->students[0], true); 1912 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign'))); 1913 1914 // Check that the student now does not have a button for Submit. 1915 $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign'))); 1916 1917 // Check that the student now has a submission history. 1918 $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign'))); 1919 1920 // Add a second submission. 1921 $now = time(); 1922 $submission = $assign->get_user_submission($this->students[0]->id, true, 1); 1923 $data = new stdClass(); 1924 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1925 'text' => 'Submission text', 1926 'format' => FORMAT_MOODLE); 1927 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 1928 $plugin->save($submission, $data); 1929 1930 // And now submit it for marking. 1931 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1932 $assign->testable_update_submission($submission, $this->students[0]->id, true, false); 1933 1934 // Mark the submission as passing. 1935 $this->setUser($this->teachers[0]); 1936 $data = new stdClass(); 1937 $data->grade = '80.0'; 1938 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1); 1939 1940 // Check that the student does not have a button for Add a new attempt. 1941 $this->setUser($this->students[0]); 1942 $output = $assign->view_student_summary($this->students[0], true); 1943 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign'))); 1944 1945 // Re-mark the submission as not passing. 1946 $this->setUser($this->teachers[0]); 1947 $data = new stdClass(); 1948 $data->grade = '50.0'; 1949 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1); 1950 1951 // Check that the student now has a button for Add a new attempt. 1952 $this->setUser($this->students[0]); 1953 $output = $assign->view_student_summary($this->students[0], true); 1954 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign'))); 1955 1956 // Add a submission as a second student. 1957 $this->setUser($this->students[1]); 1958 $now = time(); 1959 $submission = $assign->get_user_submission($this->students[1]->id, true); 1960 $data = new stdClass(); 1961 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1962 'text' => 'Submission text', 1963 'format' => FORMAT_MOODLE); 1964 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 1965 $plugin->save($submission, $data); 1966 1967 // And now submit it for marking. 1968 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1969 $assign->testable_update_submission($submission, $this->students[1]->id, true, false); 1970 1971 // Mark the submission as passing. 1972 $this->setUser($this->teachers[0]); 1973 $data = new stdClass(); 1974 $data->grade = '100.0'; 1975 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0); 1976 1977 // Check the student can see the grade. 1978 $this->setUser($this->students[1]); 1979 $output = $assign->view_student_summary($this->students[1], true); 1980 $this->assertNotEquals(false, strpos($output, '100.0')); 1981 1982 // Check that the student does not have a button for Add a new attempt. 1983 $output = $assign->view_student_summary($this->students[1], true); 1984 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign'))); 1985 1986 // Set grade to pass to 0, so that no attempts should reopen. 1987 $gradeitem = $assign->get_grade_item(); 1988 $gradeitem->gradepass = '0'; 1989 $gradeitem->update(); 1990 1991 // Add another submission. 1992 $this->setUser($this->students[2]); 1993 $now = time(); 1994 $submission = $assign->get_user_submission($this->students[2]->id, true); 1995 $data = new stdClass(); 1996 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(), 1997 'text' => 'Submission text', 1998 'format' => FORMAT_MOODLE); 1999 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 2000 $plugin->save($submission, $data); 2001 2002 // And now submit it for marking. 2003 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 2004 $assign->testable_update_submission($submission, $this->students[2]->id, true, false); 2005 2006 // Mark the submission as graded. 2007 $this->setUser($this->teachers[0]); 2008 $data = new stdClass(); 2009 $data->grade = '0.0'; 2010 $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0); 2011 2012 // Check the student can see the grade. 2013 $this->setUser($this->students[2]); 2014 $output = $assign->view_student_summary($this->students[2], true); 2015 $this->assertNotEquals(false, strpos($output, '0.0')); 2016 2017 // Check that the student does not have a button for Add a new attempt. 2018 $output = $assign->view_student_summary($this->students[2], true); 2019 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign'))); 2020 } 2021 2022 2023 public function test_markingworkflow() { 2024 global $PAGE; 2025 2026 $this->setUser($this->editingteachers[0]); 2027 $assign = $this->create_instance(array('markingworkflow'=>1)); 2028 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 2029 2030 // Mark the submission and set to notmarked. 2031 $this->setUser($this->teachers[0]); 2032 $data = new stdClass(); 2033 $data->grade = '50.0'; 2034 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED; 2035 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 2036 2037 // Check the student can't see the grade. 2038 $this->setUser($this->students[0]); 2039 $output = $assign->view_student_summary($this->students[0], true); 2040 $this->assertEquals(false, strpos($output, '50.0')); 2041 2042 // Make sure the grade isn't pushed to the gradebook. 2043 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id); 2044 $this->assertEmpty($grades); 2045 2046 // Mark the submission and set to inmarking. 2047 $this->setUser($this->teachers[0]); 2048 $data = new stdClass(); 2049 $data->grade = '50.0'; 2050 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INMARKING; 2051 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 2052 2053 // Check the student can't see the grade. 2054 $this->setUser($this->students[0]); 2055 $output = $assign->view_student_summary($this->students[0], true); 2056 $this->assertEquals(false, strpos($output, '50.0')); 2057 2058 // Make sure the grade isn't pushed to the gradebook. 2059 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id); 2060 $this->assertEmpty($grades); 2061 2062 // Mark the submission and set to readyforreview. 2063 $this->setUser($this->teachers[0]); 2064 $data = new stdClass(); 2065 $data->grade = '50.0'; 2066 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW; 2067 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 2068 2069 // Check the student can't see the grade. 2070 $this->setUser($this->students[0]); 2071 $output = $assign->view_student_summary($this->students[0], true); 2072 $this->assertEquals(false, strpos($output, '50.0')); 2073 2074 // Make sure the grade isn't pushed to the gradebook. 2075 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id); 2076 $this->assertEmpty($grades); 2077 2078 // Mark the submission and set to inreview. 2079 $this->setUser($this->teachers[0]); 2080 $data = new stdClass(); 2081 $data->grade = '50.0'; 2082 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW; 2083 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 2084 2085 // Check the student can't see the grade. 2086 $this->setUser($this->students[0]); 2087 $output = $assign->view_student_summary($this->students[0], true); 2088 $this->assertEquals(false, strpos($output, '50.0')); 2089 2090 // Make sure the grade isn't pushed to the gradebook. 2091 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id); 2092 $this->assertEmpty($grades); 2093 2094 // Mark the submission and set to readyforrelease. 2095 $this->setUser($this->teachers[0]); 2096 $data = new stdClass(); 2097 $data->grade = '50.0'; 2098 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE; 2099 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 2100 2101 // Check the student can't see the grade. 2102 $this->setUser($this->students[0]); 2103 $output = $assign->view_student_summary($this->students[0], true); 2104 $this->assertEquals(false, strpos($output, '50.0')); 2105 2106 // Make sure the grade isn't pushed to the gradebook. 2107 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id); 2108 $this->assertEmpty($grades); 2109 2110 // Mark the submission and set to released. 2111 $this->setUser($this->teachers[0]); 2112 $data = new stdClass(); 2113 $data->grade = '50.0'; 2114 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED; 2115 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 2116 2117 // Check the student can see the grade. 2118 $this->setUser($this->students[0]); 2119 $output = $assign->view_student_summary($this->students[0], true); 2120 $this->assertNotEquals(false, strpos($output, '50.0')); 2121 2122 // Make sure the grade is pushed to the gradebook. 2123 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id); 2124 $this->assertEquals(50, (int)$grades[$this->students[0]->id]->rawgrade); 2125 } 2126 2127 public function test_markerallocation() { 2128 global $PAGE; 2129 2130 $this->setUser($this->editingteachers[0]); 2131 $assign = $this->create_instance(array('markingworkflow'=>1, 'markingallocation'=>1)); 2132 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 2133 2134 // Allocate marker to submission. 2135 $data = new stdClass(); 2136 $data->allocatedmarker = $this->teachers[0]->id; 2137 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0); 2138 2139 // Check the allocated marker can view the submission. 2140 $this->setUser($this->teachers[0]); 2141 $gradingtable = new assign_grading_table($assign, 100, '', 0, true); 2142 $output = $assign->get_renderer()->render($gradingtable); 2143 $this->assertEquals(true, strpos($output, $this->students[0]->lastname)); 2144 2145 // Check that other teachers can't view this submission. 2146 $this->setUser($this->teachers[1]); 2147 $gradingtable = new assign_grading_table($assign, 100, '', 0, true); 2148 $output = $assign->get_renderer()->render($gradingtable); 2149 $this->assertNotEquals(true, strpos($output, $this->students[0]->lastname)); 2150 } 2151 2152 /** 2153 * @expectedException moodle_exception 2154 */ 2155 public function test_teacher_submit_for_student() { 2156 global $PAGE; 2157 2158 $this->preventResetByRollback(); 2159 $sink = $this->redirectMessages(); 2160 2161 $this->setUser($this->editingteachers[0]); 2162 2163 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1)); 2164 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 2165 2166 $this->setUser($this->students[0]); 2167 // Simulate a submission. 2168 $data = new stdClass(); 2169 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 2170 'text'=>'Student submission text', 2171 'format'=>FORMAT_MOODLE); 2172 2173 $notices = array(); 2174 $assign->save_submission($data, $notices); 2175 2176 // Check that the submission text was saved. 2177 $output = $assign->view_student_summary($this->students[0], true); 2178 $this->assertContains('Student submission text', $output, 'Contains student submission text'); 2179 2180 // Check that a teacher teacher with the extra capability can edit a students submission. 2181 $this->setUser($this->teachers[0]); 2182 $data = new stdClass(); 2183 $data->userid = $this->students[0]->id; 2184 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 2185 'text'=>'Teacher edited submission text', 2186 'format'=>FORMAT_MOODLE); 2187 2188 // Add the required capability. 2189 $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description'); 2190 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id); 2191 role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id); 2192 accesslib_clear_all_caches_for_unit_testing(); 2193 2194 // Try to save the submission. 2195 $notices = array(); 2196 $assign->save_submission($data, $notices); 2197 2198 // Check that the teacher can submit the students work. 2199 $data = new stdClass(); 2200 $data->userid = $this->students[0]->id; 2201 $notices = array(); 2202 $assign->submit_for_grading($data, $notices); 2203 2204 // Revert to draft so the student can edit it. 2205 $assign->revert_to_draft($this->students[0]->id); 2206 2207 $this->setUser($this->students[0]); 2208 2209 // Check that the submission text was saved. 2210 $output = $assign->view_student_summary($this->students[0], true); 2211 $this->assertContains('Teacher edited submission text', $output, 'Contains student submission text'); 2212 2213 // Check that the student can submit their work. 2214 $data = new stdClass(); 2215 $assign->submit_for_grading($data, $notices); 2216 2217 $output = $assign->view_student_summary($this->students[0], true); 2218 $this->assertNotContains(get_string('addsubmission', 'assign'), $output); 2219 2220 // Set to a default editing teacher who should not be able to edit this submission. 2221 $this->setUser($this->editingteachers[1]); 2222 2223 // Revert to draft so the submission is editable. 2224 $assign->revert_to_draft($this->students[0]->id); 2225 2226 $data = new stdClass(); 2227 $data->userid = $this->students[0]->id; 2228 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 2229 'text'=>'Teacher 2 edited submission text', 2230 'format'=>FORMAT_MOODLE); 2231 2232 $notices = array(); 2233 $assign->save_submission($data, $notices); 2234 2235 $sink->close(); 2236 } 2237 2238 public function test_disable_submit_after_cutoff_date() { 2239 global $PAGE; 2240 2241 $this->setUser($this->editingteachers[0]); 2242 $now = time(); 2243 $tomorrow = $now + 24*60*60; 2244 $lastweek = $now - 7*24*60*60; 2245 $yesterday = $now - 24*60*60; 2246 2247 $assign = $this->create_instance(array('duedate'=>$yesterday, 2248 'cutoffdate'=>$tomorrow, 2249 'assignsubmission_onlinetext_enabled'=>1)); 2250 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 2251 2252 // Student should be able to see an add submission button. 2253 $this->setUser($this->students[0]); 2254 $output = $assign->view_student_summary($this->students[0], true); 2255 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign'))); 2256 2257 // Add a submission but don't submit now. 2258 $submission = $assign->get_user_submission($this->students[0]->id, true); 2259 $data = new stdClass(); 2260 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 2261 'text'=>'Submission text', 2262 'format'=>FORMAT_MOODLE); 2263 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 2264 $plugin->save($submission, $data); 2265 2266 // Create another instance with cut-off and due-date already passed. 2267 $this->setUser($this->editingteachers[0]); 2268 $now = time(); 2269 $assign = $this->create_instance(array('duedate'=>$lastweek, 2270 'cutoffdate'=>$yesterday, 2271 'assignsubmission_onlinetext_enabled'=>1)); 2272 2273 $this->setUser($this->students[0]); 2274 $output = $assign->view_student_summary($this->students[0], true); 2275 $this->assertNotContains($output, get_string('editsubmission', 'assign'), 2276 'Should not be able to edit after cutoff date.'); 2277 $this->assertNotContains($output, get_string('submitassignment', 'assign'), 2278 'Should not be able to submit after cutoff date.'); 2279 } 2280 /** 2281 * Testing for submission comment plugin settings 2282 */ 2283 public function test_submission_comment_plugin_settings() { 2284 global $CFG; 2285 2286 $commentconfig = false; 2287 if (!empty($CFG->usecomments)) { 2288 $commentconfig = $CFG->usecomments; 2289 } 2290 2291 $CFG->usecomments = true; 2292 $assign = $this->create_instance(); 2293 $plugin = $assign->get_submission_plugin_by_type('comments'); 2294 $this->assertEquals(1, $plugin->is_enabled('enabled')); 2295 2296 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0)); 2297 $plugin = $assign->get_submission_plugin_by_type('comments'); 2298 $this->assertEquals(1, $plugin->is_enabled('enabled')); 2299 2300 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1)); 2301 $plugin = $assign->get_submission_plugin_by_type('comments'); 2302 $this->assertEquals(1, $plugin->is_enabled('enabled')); 2303 2304 $CFG->usecomments = false; 2305 $assign = $this->create_instance(); 2306 $plugin = $assign->get_submission_plugin_by_type('comments'); 2307 $this->assertEquals(0, $plugin->is_enabled('enabled')); 2308 2309 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0)); 2310 $plugin = $assign->get_submission_plugin_by_type('comments'); 2311 $this->assertEquals(0, $plugin->is_enabled('enabled')); 2312 2313 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1)); 2314 $plugin = $assign->get_submission_plugin_by_type('comments'); 2315 $this->assertEquals(0, $plugin->is_enabled('enabled')); 2316 2317 $CFG->usecomments = $commentconfig; 2318 } 2319 2320 /** 2321 * Testing for comment inline settings 2322 */ 2323 public function test_feedback_comment_commentinline() { 2324 global $CFG; 2325 2326 $sourcetext = "Hello! 2327 2328 I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness. 2329 2330 URL outside a tag: https://moodle.org/logo/logo-240x60.gif 2331 Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif 2332 2333 External link 1:<img src='https://moodle.org/logo/logo-240x60.gif' alt='Moodle'/> 2334 External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\"/> 2335 Internal link 1:<img src='@@PLUGINFILE@@/logo-240x60.gif' alt='Moodle'/> 2336 Internal link 2:<img alt=\"Moodle\" src=\"@@PLUGINFILE@@logo-240x60.gif\"/> 2337 Anchor link 1:<a href=\"@@PLUGINFILE@@logo-240x60.gif\" alt=\"bananas\">Link text</a> 2338 Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a> 2339 "; 2340 2341 // Note the internal images have been stripped and the html is purified (quotes fixed in this case). 2342 $filteredtext = "Hello! 2343 2344 I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness. 2345 2346 URL outside a tag: https://moodle.org/logo/logo-240x60.gif 2347 Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif 2348 2349 External link 1:<img src=\"https://moodle.org/logo/logo-240x60.gif\" alt=\"Moodle\" /> 2350 External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\" /> 2351 Internal link 1: 2352 Internal link 2: 2353 Anchor link 1:Link text 2354 Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a> 2355 "; 2356 2357 $this->setUser($this->editingteachers[0]); 2358 $params = array('assignsubmission_onlinetext_enabled' => 1, 2359 'assignfeedback_comments_enabled' => 1, 2360 'assignfeedback_comments_commentinline' => 1); 2361 $assign = $this->create_instance($params); 2362 2363 $this->setUser($this->students[0]); 2364 // Add a submission but don't submit now. 2365 $submission = $assign->get_user_submission($this->students[0]->id, true); 2366 $data = new stdClass(); 2367 2368 // Test the internal link is stripped, but the external one is not. 2369 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(), 2370 'text'=>$sourcetext, 2371 'format'=>FORMAT_MOODLE); 2372 2373 $plugin = $assign->get_submission_plugin_by_type('onlinetext'); 2374 $plugin->save($submission, $data); 2375 2376 $this->setUser($this->editingteachers[0]); 2377 2378 $data = new stdClass(); 2379 require_once($CFG->dirroot . '/mod/assign/gradeform.php'); 2380 $pagination = array('userid'=>$this->students[0]->id, 2381 'rownum'=>0, 2382 'last'=>true, 2383 'useridlistid' => $assign->get_useridlist_key_id(), 2384 'attemptnumber'=>0); 2385 $formparams = array($assign, $data, $pagination); 2386 $mform = new mod_assign_grade_form(null, $formparams); 2387 2388 $this->assertEquals($filteredtext, $data->assignfeedbackcomments_editor['text']); 2389 } 2390 2391 /** 2392 * Testing for feedback comment plugin settings 2393 */ 2394 public function test_feedback_plugin_settings() { 2395 2396 $assign = $this->create_instance(); 2397 $plugin = $assign->get_feedback_plugin_by_type('comments'); 2398 $this->assertEquals(0, $plugin->is_enabled('enabled')); 2399 2400 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 0)); 2401 $plugin = $assign->get_feedback_plugin_by_type('comments'); 2402 $this->assertEquals(0, $plugin->is_enabled('enabled')); 2403 2404 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1)); 2405 $plugin = $assign->get_feedback_plugin_by_type('comments'); 2406 $this->assertEquals(1, $plugin->is_enabled('enabled')); 2407 } 2408 2409 /** 2410 * Testing if gradebook feedback plugin is enabled. 2411 */ 2412 public function test_is_gradebook_feedback_enabled() { 2413 $adminconfig = get_config('assign'); 2414 $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; 2415 2416 // Create assignment with gradebook feedback enabled and grade = 0. 2417 $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 1, 'grades' => 0)); 2418 2419 // Get gradebook feedback plugin. 2420 $gradebookplugintype = str_replace('assignfeedback_', '', $gradebookplugin); 2421 $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype); 2422 $this->assertEquals(1, $plugin->is_enabled('enabled')); 2423 $this->assertEquals(1, $assign->is_gradebook_feedback_enabled()); 2424 2425 // Create assignment with gradebook feedback disabled and grade = 0. 2426 $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 0, 'grades' => 0)); 2427 $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype); 2428 $this->assertEquals(0, $plugin->is_enabled('enabled')); 2429 } 2430 2431 /** 2432 * Testing can_edit_submission 2433 */ 2434 public function test_can_edit_submission() { 2435 global $PAGE, $DB; 2436 $this->create_extra_users(); 2437 2438 $this->setAdminUser(); 2439 // Create assignment (onlinetext). 2440 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1)); 2441 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); 2442 2443 // Check student can edit their own submission. 2444 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->students[0]->id)); 2445 // Check student cannot edit others submission. 2446 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->students[1]->id)); 2447 2448 // Check teacher cannot (by default) edit a students submission. 2449 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id)); 2450 2451 // Add the required capability to edit a student submission. 2452 $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description'); 2453 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id); 2454 role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id); 2455 accesslib_clear_all_caches_for_unit_testing(); 2456 // Retest - should now have access. 2457 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id)); 2458 2459 // Force create an assignment with SEPARATEGROUPS. 2460 $data = new stdClass(); 2461 $data->courseid = $this->course->id; 2462 $data->name = 'Grouping'; 2463 $groupingid = groups_create_grouping($data); 2464 groups_assign_grouping($groupingid, $this->groups[0]->id); 2465 groups_assign_grouping($groupingid, $this->groups[1]->id); 2466 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS)); 2467 2468 // Add the capability to the new assignment for extra students 0 and 1. 2469 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id); 2470 role_assign($roleid, $this->extrastudents[0]->id, $assign->get_context()->id); 2471 role_assign($roleid, $this->extrastudents[1]->id, $assign->get_context()->id); 2472 accesslib_clear_all_caches_for_unit_testing(); 2473 2474 // Verify the extra student does not have the capability to edit a submission not in their group. 2475 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[1]->id)); 2476 // Verify the extra student does have the capability to edit a submission in their group. 2477 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[0]->id)); 2478 2479 } 2480 2481 /** 2482 * Test if the view blind details capability works 2483 */ 2484 public function test_can_view_blind_details() { 2485 global $PAGE, $DB; 2486 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher')); 2487 $managerrole = $DB->get_record('role', array('shortname' => 'manager')); 2488 2489 $student = $this->students[0];// Get a student user. 2490 // Create a teacher. Shouldn't be able to view blind marking ID. 2491 $teacher = $this->getDataGenerator()->create_user(); 2492 2493 $this->getDataGenerator()->enrol_user($teacher->id, 2494 $this->course->id, 2495 $teacherrole->id); 2496 2497 // Create a manager.. Should be able to view blind marking ID. 2498 $manager = $this->getDataGenerator()->create_user(); 2499 $this->getDataGenerator()->enrol_user($manager->id, 2500 $this->course->id, 2501 $managerrole->id); 2502 2503 // Generate blind marking assignment. 2504 $assign = $this->create_instance(array('blindmarking' => 1)); 2505 $this->assertEquals(true, $assign->is_blind_marking()); 2506 2507 // Test student names are hidden to teacher. 2508 $this->setUser($teacher); 2509 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 2510 $output = $assign->get_renderer()->render($gradingtable); 2511 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign'))); // "Participant" is somewhere on the page. 2512 $this->assertEquals(false, strpos($output, fullname($student))); // Students full name doesn't appear. 2513 2514 // Test student names are visible to manager. 2515 $this->setUser($manager); 2516 $gradingtable = new assign_grading_table($assign, 1, '', 0, true); 2517 $output = $assign->get_renderer()->render($gradingtable); 2518 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign'))); 2519 $this->assertEquals(true, strpos($output, fullname($student))); 2520 } 2521 2522 /** 2523 * Testing get_shared_group_members 2524 */ 2525 public function test_get_shared_group_members() { 2526 $this->create_extra_users(); 2527 $this->setAdminUser(); 2528 2529 // Force create an assignment with SEPARATEGROUPS. 2530 $data = new stdClass(); 2531 $data->courseid = $this->course->id; 2532 $data->name = 'Grouping'; 2533 $groupingid = groups_create_grouping($data); 2534 groups_assign_grouping($groupingid, $this->groups[0]->id); 2535 groups_assign_grouping($groupingid, $this->groups[1]->id); 2536 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS)); 2537 $cm = $assign->get_course_module(); 2538 2539 // Add the capability to access allgroups. 2540 $roleid = create_role('Access all groups role', 'accessallgroupsrole', ''); 2541 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $assign->get_context()->id); 2542 role_assign($roleid, $this->extrastudents[3]->id, $assign->get_context()->id); 2543 accesslib_clear_all_caches_for_unit_testing(); 2544 2545 // Get shared group members for students 0 and 1. 2546 $groupmembers = array(); 2547 $groupmembers[0] = $assign->get_shared_group_members($cm, $this->students[0]->id); 2548 $groupmembers[1] = $assign->get_shared_group_members($cm, $this->students[1]->id); 2549 2550 // They should share groups with extrastudents 0 and 1. 2551 $this->assertTrue(in_array($this->extrastudents[0]->id, $groupmembers[0])); 2552 $this->assertFalse(in_array($this->extrastudents[0]->id, $groupmembers[1])); 2553 $this->assertTrue(in_array($this->extrastudents[1]->id, $groupmembers[1])); 2554 $this->assertFalse(in_array($this->extrastudents[1]->id, $groupmembers[0])); 2555 2556 // Lists of group members for students and extrastudents should be the same. 2557 $this->assertEquals($groupmembers[0], $assign->get_shared_group_members($cm, $this->extrastudents[0]->id)); 2558 $this->assertEquals($groupmembers[1], $assign->get_shared_group_members($cm, $this->extrastudents[1]->id)); 2559 2560 // Get all group members for extrastudent 3 wich can access all groups. 2561 $allgroupmembers = $assign->get_shared_group_members($cm, $this->extrastudents[3]->id); 2562 2563 // Extrastudent 3 should see students 0 and 1, extrastudent 0 and 1. 2564 $this->assertTrue(in_array($this->students[0]->id, $allgroupmembers)); 2565 $this->assertTrue(in_array($this->students[1]->id, $allgroupmembers)); 2566 $this->assertTrue(in_array($this->extrastudents[0]->id, $allgroupmembers)); 2567 $this->assertTrue(in_array($this->extrastudents[1]->id , $allgroupmembers)); 2568 } 2569 2570 /** 2571 * Test get plugins file areas 2572 */ 2573 public function test_get_plugins_file_areas() { 2574 $this->setUser($this->editingteachers[0]); 2575 $assign = $this->create_instance(); 2576 2577 // Test that all the submission and feedback plugins are returning the expected file aras. 2578 $usingfilearea = 0; 2579 $coreplugins = core_plugin_manager::standard_plugins_list('assignsubmission'); 2580 foreach ($assign->get_submission_plugins() as $plugin) { 2581 $type = $plugin->get_type(); 2582 if (!in_array($type, $coreplugins)) { 2583 continue; 2584 } 2585 $fileareas = $plugin->get_file_areas(); 2586 2587 if ($type == 'onlinetext') { 2588 $this->assertEquals(array('submissions_onlinetext' => 'Online text'), $fileareas); 2589 $usingfilearea++; 2590 } else if ($type == 'file') { 2591 $this->assertEquals(array('submission_files' => 'File submissions'), $fileareas); 2592 $usingfilearea++; 2593 } else { 2594 $this->assertEmpty($fileareas); 2595 } 2596 } 2597 $this->assertEquals(2, $usingfilearea); 2598 2599 $usingfilearea = 0; 2600 $coreplugins = core_plugin_manager::standard_plugins_list('assignfeedback'); 2601 foreach ($assign->get_feedback_plugins() as $plugin) { 2602 $type = $plugin->get_type(); 2603 if (!in_array($type, $coreplugins)) { 2604 continue; 2605 } 2606 $fileareas = $plugin->get_file_areas(); 2607 2608 if ($type == 'editpdf') { 2609 $this->assertEquals(array('download' => 'Annotate PDF'), $fileareas); 2610 $usingfilearea++; 2611 } else if ($type == 'file') { 2612 $this->assertEquals(array('feedback_files' => 'Feedback files'), $fileareas); 2613 $usingfilearea++; 2614 } else { 2615 $this->assertEmpty($fileareas); 2616 } 2617 } 2618 $this->assertEquals(2, $usingfilearea); 2619 } 2620 2621 /** 2622 * Test the quicksave grades processor 2623 */ 2624 public function test_process_save_quick_grades() { 2625 $this->editingteachers[0]->ignoresesskey = true; 2626 $this->setUser($this->editingteachers[0]); 2627 2628 $assign = $this->create_instance(array('attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL)); 2629 2630 // Initially grade the user. 2631 $grade = $assign->get_user_grade($this->students[0]->id, false); 2632 if (!$grade) { 2633 $grade = new stdClass(); 2634 $grade->attemptnumber = ''; 2635 $grade->timemodified = ''; 2636 } 2637 $data = array( 2638 'grademodified_' . $this->students[0]->id => $grade->timemodified, 2639 'gradeattempt_' . $this->students[0]->id => $grade->attemptnumber, 2640 'quickgrade_' . $this->students[0]->id => '60.0' 2641 ); 2642 $result = $assign->testable_process_save_quick_grades($data); 2643 $this->assertContains(get_string('quickgradingchangessaved', 'assign'), $result); 2644 $grade = $assign->get_user_grade($this->students[0]->id, false); 2645 $this->assertEquals('60.0', $grade->grade); 2646 2647 // Attempt to grade with a past attempts grade info. 2648 $assign->testable_process_add_attempt($this->students[0]->id); 2649 $data = array( 2650 'grademodified_' . $this->students[0]->id => $grade->timemodified, 2651 'gradeattempt_' . $this->students[0]->id => $grade->attemptnumber, 2652 'quickgrade_' . $this->students[0]->id => '50.0' 2653 ); 2654 $result = $assign->testable_process_save_quick_grades($data); 2655 $this->assertContains(get_string('errorrecordmodified', 'assign'), $result); 2656 $grade = $assign->get_user_grade($this->students[0]->id, false); 2657 $this->assertFalse($grade); 2658 2659 // Attempt to grade a the attempt. 2660 $submission = $assign->get_user_submission($this->students[0]->id, false); 2661 $data = array( 2662 'grademodified_' . $this->students[0]->id => '', 2663 'gradeattempt_' . $this->students[0]->id => $submission->attemptnumber, 2664 'quickgrade_' . $this->students[0]->id => '40.0' 2665 ); 2666 $result = $assign->testable_process_save_quick_grades($data); 2667 $this->assertContains(get_string('quickgradingchangessaved', 'assign'), $result); 2668 $grade = $assign->get_user_grade($this->students[0]->id, false); 2669 $this->assertEquals('40.0', $grade->grade); 2670 2671 // Catch grade update conflicts. 2672 // Save old data for later. 2673 $pastdata = $data; 2674 // Update the grade the 'good' way. 2675 $data = array( 2676 'grademodified_' . $this->students[0]->id => $grade->timemodified, 2677 'gradeattempt_' . $this->students[0]->id => $grade->attemptnumber, 2678 'quickgrade_' . $this->students[0]->id => '30.0' 2679 ); 2680 $result = $assign->testable_process_save_quick_grades($data); 2681 $this->assertContains(get_string('quickgradingchangessaved', 'assign'), $result); 2682 $grade = $assign->get_user_grade($this->students[0]->id, false); 2683 $this->assertEquals('30.0', $grade->grade); 2684 2685 // Now update using 'old' data. Should fail. 2686 $result = $assign->testable_process_save_quick_grades($pastdata); 2687 $this->assertContains(get_string('errorrecordmodified', 'assign'), $result); 2688 $grade = $assign->get_user_grade($this->students[0]->id, false); 2689 $this->assertEquals('30.0', $grade->grade); 2690 } 2691 2692 /** 2693 * Test updating activity completion when submitting an assessment. 2694 */ 2695 public function test_update_activity_completion_records_solitary_submission() { 2696 $assign = $this->create_instance(array('grade' => 100, 2697 'completion' => COMPLETION_TRACKING_AUTOMATIC, 2698 'requireallteammemberssubmit' => 0)); 2699 2700 $cm = $assign->get_course_module(); 2701 2702 $student = $this->students[0]; 2703 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 2704 2705 $this->setUser($student); 2706 2707 // Simulate a submission. 2708 $data = new stdClass(); 2709 $data->onlinetext_editor = array( 2710 'itemid' => file_get_unused_draft_itemid(), 2711 'text' => 'Student submission text', 2712 'format' => FORMAT_MOODLE 2713 ); 2714 $completion = new completion_info($this->course); 2715 2716 $notices = array(); 2717 $assign->save_submission($data, $notices); 2718 2719 $submission = $assign->get_user_submission($student->id, true); 2720 2721 // Check that completion is not met yet. 2722 $completiondata = $completion->get_data($cm, false, $student->id); 2723 $this->assertEquals(0, $completiondata->completionstate); 2724 $assign->testable_update_activity_completion_records(0, 0, $submission, 2725 $student->id, COMPLETION_COMPLETE, $completion); 2726 // Completion should now be met. 2727 $completiondata = $completion->get_data($cm, false, $student->id); 2728 $this->assertEquals(1, $completiondata->completionstate); 2729 } 2730 2731 /** 2732 * Test updating activity completion when submitting an assessment. 2733 */ 2734 public function test_update_activity_completion_records_team_submission() { 2735 $assign = $this->create_instance(array('grade' => 100, 2736 'completion' => COMPLETION_TRACKING_AUTOMATIC, 2737 'teamsubmission' => 1)); 2738 2739 $cm = $assign->get_course_module(); 2740 2741 $student1 = $this->students[0]; 2742 $student2 = $this->students[1]; 2743 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 2744 2745 // Put both users into a group. 2746 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id)); 2747 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $student1->id)); 2748 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $student2->id)); 2749 2750 $this->setUser($student1); 2751 2752 // Simulate a submission. 2753 $data = new stdClass(); 2754 $data->onlinetext_editor = array( 2755 'itemid' => file_get_unused_draft_itemid(), 2756 'text' => 'Student submission text', 2757 'format' => FORMAT_MOODLE 2758 ); 2759 $completion = new completion_info($this->course); 2760 2761 $notices = array(); 2762 $assign->save_submission($data, $notices); 2763 2764 $submission = $assign->get_user_submission($student1->id, true); 2765 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 2766 $submission->groupid = $group1->id; 2767 2768 // Check that completion is not met yet. 2769 $completiondata = $completion->get_data($cm, false, $student1->id); 2770 $this->assertEquals(0, $completiondata->completionstate); 2771 $completiondata = $completion->get_data($cm, false, $student2->id); 2772 $this->assertEquals(0, $completiondata->completionstate); 2773 $assign->testable_update_activity_completion_records(1, 0, $submission, $student1->id, 2774 COMPLETION_COMPLETE, $completion); 2775 // Completion should now be met. 2776 $completiondata = $completion->get_data($cm, false, $student1->id); 2777 $this->assertEquals(1, $completiondata->completionstate); 2778 $completiondata = $completion->get_data($cm, false, $student2->id); 2779 $this->assertEquals(1, $completiondata->completionstate); 2780 } 2781 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |