[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mod/assign/tests/ -> locallib_test.php (source)

   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->setExpectedException('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->setExpectedException('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->setExpectedException('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       * Test submissions with extension date.
 123       */
 124      public function test_gradingtable_extension_due_date() {
 125          global $PAGE;
 126  
 127          // Setup the assignment.
 128          $this->create_extra_users();
 129          $this->setUser($this->editingteachers[0]);
 130          $assign = $this->create_instance(array(
 131              'assignsubmission_onlinetext_enabled'=>1,
 132              'duedate' => time() - 4 * 24 * 60 * 60,
 133           ));
 134          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
 135              'id' => $assign->get_course_module()->id,
 136              'action' => 'grading',
 137          )));
 138  
 139          // Check that the assignment is late.
 140          $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
 141          $output = $assign->get_renderer()->render($gradingtable);
 142          $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
 143          $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60)), $output);
 144  
 145          // Grant an extension.
 146          $extendedtime = time() + 2 * 24 * 60 * 60;
 147          $assign->testable_save_user_extension($this->students[0]->id, $extendedtime);
 148          $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
 149          $output = $assign->get_renderer()->render($gradingtable);
 150          $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
 151          $this->assertContains(get_string('userextensiondate', 'assign', userdate($extendedtime)), $output);
 152  
 153          // Simulate a submission.
 154          $this->setUser($this->students[0]);
 155          $submission = $assign->get_user_submission($this->students[0]->id, true);
 156          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 157          $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
 158          $data = new stdClass();
 159          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 160                                           'text'=>'Submission text',
 161                                           'format'=>FORMAT_MOODLE);
 162          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 163          $plugin->save($submission, $data);
 164  
 165          // Verify output.
 166          $this->setUser($this->editingteachers[0]);
 167          $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
 168          $output = $assign->get_renderer()->render($gradingtable);
 169          $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output);
 170          $this->assertContains(get_string('userextensiondate', 'assign', userdate($extendedtime)), $output);
 171      }
 172  
 173      /**
 174       * Test that late submissions with extension date calculate correctly.
 175       */
 176      public function test_gradingtable_extension_date_calculation_for_lateness() {
 177          global $PAGE;
 178  
 179          // Setup the assignment.
 180          $this->create_extra_users();
 181          $this->setUser($this->editingteachers[0]);
 182          $time = time();
 183          $assign = $this->create_instance(array(
 184              'assignsubmission_onlinetext_enabled'=>1,
 185              'duedate' => $time - 4 * 24 * 60 * 60,
 186           ));
 187          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
 188              'id' => $assign->get_course_module()->id,
 189              'action' => 'grading',
 190          )));
 191  
 192          // Check that the assignment is late.
 193          $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
 194          $output = $assign->get_renderer()->render($gradingtable);
 195          $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
 196          $difftime = time() - $time;
 197          $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60 + $difftime)), $output);
 198  
 199          // Grant an extension that is in the past.
 200          $assign->testable_save_user_extension($this->students[0]->id, $time - 2 * 24 * 60 * 60);
 201          $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
 202          $output = $assign->get_renderer()->render($gradingtable);
 203          $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
 204          $this->assertContains(get_string('userextensiondate', 'assign', userdate($time - 2*24*60*60)), $output);
 205          $difftime = time() - $time;
 206          $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60 + $difftime)), $output);
 207  
 208          // Simulate a submission.
 209          $this->setUser($this->students[0]);
 210          $submission = $assign->get_user_submission($this->students[0]->id, true);
 211          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 212          $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
 213          $data = new stdClass();
 214          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 215                                           'text'=>'Submission text',
 216                                           'format'=>FORMAT_MOODLE);
 217          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 218          $plugin->save($submission, $data);
 219          $submittedtime = time();
 220  
 221          // Verify output.
 222          $this->setUser($this->editingteachers[0]);
 223          $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
 224          $output = $assign->get_renderer()->render($gradingtable);
 225          $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output);
 226          $this->assertContains(get_string('userextensiondate', 'assign', userdate($time - 2*24*60*60)), $output);
 227  
 228          $difftime = $submittedtime - $time;
 229          $this->assertContains(get_string('submittedlateshort', 'assign', format_time(2*24*60*60 + $difftime)), $output);
 230      }
 231  
 232      /**
 233       * Check that group submission information is rendered correctly in the
 234       * grading table.
 235       */
 236      public function test_gradingtable_group_submissions_rendering() {
 237          global $PAGE;
 238  
 239          $this->create_extra_users();
 240          // Now verify group assignments.
 241          $this->setUser($this->teachers[0]);
 242          $assign = $this->create_instance(array(
 243              'teamsubmission' => 1,
 244              'assignsubmission_onlinetext_enabled' => 1,
 245              'submissiondrafts' => 1,
 246              'requireallteammemberssubmit' => 0,
 247          ));
 248          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
 249              'id' => $assign->get_course_module()->id,
 250              'action' => 'grading',
 251          )));
 252  
 253          // Add a submission.
 254          $this->setUser($this->extrastudents[0]);
 255          $data = new stdClass();
 256          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 257                                           'text'=>'Submission text',
 258                                           'format'=>FORMAT_MOODLE);
 259          $notices = array();
 260          $assign->save_submission($data, $notices);
 261  
 262          $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
 263          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 264          $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
 265  
 266          // Check output.
 267          $this->setUser($this->teachers[0]);
 268          $gradingtable = new assign_grading_table($assign, 4, '', 0, true);
 269          $output = $assign->get_renderer()->render($gradingtable);
 270          $document = new DOMDocument();
 271          $document->loadHTML($output);
 272          $xpath = new DOMXPath($document);
 273  
 274          // Check status.
 275          $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c4"]/div[@class="submissionstatussubmitted"])'));
 276          $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c4"]/div[@class="submissionstatussubmitted"])'));
 277  
 278          // Check submission last modified date
 279          $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])')));
 280          $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c8"])')));
 281  
 282          // Check group.
 283          $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c5"])'));
 284          $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c5"])'));
 285  
 286          // Check submission text.
 287          $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c9"]/div/div)'));
 288          $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c9"]/div/div)'));
 289  
 290          // Check comments can be made.
 291          $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r0_c10"]//textarea)'));
 292          $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r3_c10"]//textarea)'));
 293      }
 294  
 295      public function test_show_intro() {
 296          // Test whether we are showing the intro at the correct times.
 297          $this->setUser($this->editingteachers[0]);
 298          $assign = $this->create_instance(array('alwaysshowdescription'=>1));
 299  
 300          $this->assertEquals(true, $assign->testable_show_intro());
 301  
 302          $tomorrow = time() + (24*60*60);
 303  
 304          $assign = $this->create_instance(array('alwaysshowdescription'=>0,
 305                                                 'allowsubmissionsfromdate'=>$tomorrow));
 306          $this->assertEquals(false, $assign->testable_show_intro());
 307          $yesterday = time() - (24*60*60);
 308          $assign = $this->create_instance(array('alwaysshowdescription'=>0,
 309                                                 'allowsubmissionsfromdate'=>$yesterday));
 310          $this->assertEquals(true, $assign->testable_show_intro());
 311      }
 312  
 313      public function test_has_submissions_or_grades() {
 314          $this->setUser($this->editingteachers[0]);
 315          $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
 316  
 317          $instance = $assign->get_instance();
 318  
 319          // Should start empty.
 320          $this->assertEquals(false, $assign->has_submissions_or_grades());
 321  
 322          // Simulate a submission.
 323          $this->setUser($this->students[0]);
 324          $submission = $assign->get_user_submission($this->students[0]->id, true);
 325          $data = new stdClass();
 326          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 327                                           'text'=>'Submission text',
 328                                           'format'=>FORMAT_MOODLE);
 329          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 330          $plugin->save($submission, $data);
 331  
 332          // Now test again.
 333          $this->assertEquals(true, $assign->has_submissions_or_grades());
 334          // Set this back to default.
 335          $this->students[0]->ignoresesskey = false;
 336      }
 337  
 338      public function test_delete_grades() {
 339          $this->setUser($this->editingteachers[0]);
 340          $assign = $this->create_instance();
 341  
 342          // Simulate adding a grade.
 343          $this->setUser($this->teachers[0]);
 344          $data = new stdClass();
 345          $data->grade = '50.0';
 346          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
 347  
 348          // Now see if the data is in the gradebook.
 349          $gradinginfo = grade_get_grades($this->course->id,
 350                                          'mod',
 351                                          'assign',
 352                                          $assign->get_instance()->id);
 353  
 354          $this->assertNotEquals(0, count($gradinginfo->items));
 355  
 356          $assign->testable_delete_grades();
 357          $gradinginfo = grade_get_grades($this->course->id,
 358                                          'mod',
 359                                          'assign',
 360                                          $assign->get_instance()->id);
 361  
 362          $this->assertEquals(0, count($gradinginfo->items));
 363      }
 364  
 365      public function test_delete_instance() {
 366          $this->setUser($this->editingteachers[0]);
 367          $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
 368  
 369          // Simulate adding a grade.
 370          $this->setUser($this->teachers[0]);
 371          $data = new stdClass();
 372          $data->grade = '50.0';
 373          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
 374  
 375          // Simulate a submission.
 376          $this->setUser($this->students[0]);
 377          $submission = $assign->get_user_submission($this->students[0]->id, true);
 378          $data = new stdClass();
 379          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 380                                           'text'=>'Submission text',
 381                                           'format'=>FORMAT_MOODLE);
 382          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 383          $plugin->save($submission, $data);
 384  
 385          // Now try and delete.
 386          $this->assertEquals(true, $assign->delete_instance());
 387      }
 388  
 389      public function test_reset_userdata() {
 390          global $DB;
 391  
 392          $now = time();
 393          $this->setUser($this->editingteachers[0]);
 394          $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1,
 395                                                 'duedate'=>$now));
 396  
 397          // Simulate adding a grade.
 398          $this->setUser($this->teachers[0]);
 399          $data = new stdClass();
 400          $data->grade = '50.0';
 401          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
 402  
 403          // Simulate a submission.
 404          $this->setUser($this->students[0]);
 405          $submission = $assign->get_user_submission($this->students[0]->id, true);
 406          $data = new stdClass();
 407          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 408                                           'text'=>'Submission text',
 409                                           'format'=>FORMAT_MOODLE);
 410          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 411          $plugin->save($submission, $data);
 412  
 413          $this->assertEquals(true, $assign->has_submissions_or_grades());
 414          // Now try and reset.
 415          $data = new stdClass();
 416          $data->reset_assign_submissions = 1;
 417          $data->reset_gradebook_grades = 1;
 418          $data->courseid = $this->course->id;
 419          $data->timeshift = 24*60*60;
 420          $this->setUser($this->editingteachers[0]);
 421          $assign->reset_userdata($data);
 422          $this->assertEquals(false, $assign->has_submissions_or_grades());
 423  
 424          // Reload the instance data.
 425          $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
 426          $this->assertEquals($now + 24*60*60, $instance->duedate);
 427  
 428          // Test reset using assign_reset_userdata().
 429          $assignduedate = $instance->duedate; // Keep old updated value for comparison.
 430          $data->timeshift = 2*24*60*60;
 431          assign_reset_userdata($data);
 432          $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
 433          $this->assertEquals($assignduedate + 2*24*60*60, $instance->duedate);
 434  
 435          // Create one more assignment and reset, make sure time shifted for previous assignment is not changed.
 436          $assign2 = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1,
 437                                                 'duedate' => $now));
 438          $assignduedate = $instance->duedate;
 439          $data->timeshift = 3*24*60*60;
 440          $assign2->reset_userdata($data);
 441          $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
 442          $this->assertEquals($assignduedate, $instance->duedate);
 443          $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id));
 444          $this->assertEquals($now + 3*24*60*60, $instance2->duedate);
 445  
 446          // Reset both assignments using assign_reset_userdata() and make sure both assignments have same date.
 447          $assignduedate = $instance->duedate;
 448          $assign2duedate = $instance2->duedate;
 449          $data->timeshift = 4*24*60*60;
 450          assign_reset_userdata($data);
 451          $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
 452          $this->assertEquals($assignduedate + 4*24*60*60, $instance->duedate);
 453          $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id));
 454          $this->assertEquals($assign2duedate + 4*24*60*60, $instance2->duedate);
 455      }
 456  
 457      public function test_plugin_settings() {
 458          global $DB;
 459  
 460          $now = time();
 461          $this->setUser($this->editingteachers[0]);
 462          $assign = $this->create_instance(array('assignsubmission_file_enabled'=>1,
 463                                                 'assignsubmission_file_maxfiles'=>12,
 464                                                 'assignsubmission_file_maxsizebytes'=>10));
 465  
 466          $plugin = $assign->get_submission_plugin_by_type('file');
 467          $this->assertEquals('12', $plugin->get_config('maxfilesubmissions'));
 468      }
 469  
 470      public function test_update_calendar() {
 471          global $DB;
 472  
 473          $this->setUser($this->editingteachers[0]);
 474          $userctx = context_user::instance($this->editingteachers[0]->id)->id;
 475  
 476          // Hack to pretend that there was an editor involved. We need both $_POST and $_REQUEST, and a sesskey.
 477          $draftid = file_get_unused_draft_itemid();
 478          $_REQUEST['introeditor'] = $draftid;
 479          $_POST['introeditor'] = $draftid;
 480          $_POST['sesskey'] = sesskey();
 481  
 482          // Write links to a draft area.
 483          $fakearealink1 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">link</a>', 'draftfile.php', $userctx,
 484              'user', 'draft', $draftid);
 485          $fakearealink2 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">new</a>', 'draftfile.php', $userctx,
 486              'user', 'draft', $draftid);
 487  
 488          // Create a new assignment with links to a draft area.
 489          $now = time();
 490          $assign = $this->create_instance(array(
 491              'duedate' => $now,
 492              'intro' => $fakearealink1,
 493              'introformat' => FORMAT_HTML
 494          ));
 495  
 496          // See if there is an event in the calendar.
 497          $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
 498          $event = $DB->get_record('event', $params);
 499          $this->assertNotEmpty($event);
 500          $this->assertSame('link', $event->description);     // The pluginfile links are removed.
 501  
 502          // Make sure the same works when updating the assignment.
 503          $instance = $assign->get_instance();
 504          $instance->instance = $instance->id;
 505          $instance->intro = $fakearealink2;
 506          $instance->introformat = FORMAT_HTML;
 507          $assign->update_instance($instance);
 508          $params = array('modulename' => 'assign', 'instance' => $assign->get_instance()->id);
 509          $event = $DB->get_record('event', $params);
 510          $this->assertNotEmpty($event);
 511          $this->assertSame('new', $event->description);     // The pluginfile links are removed.
 512  
 513          // Create an assignment with a description that should be hidden.
 514          $assign = $this->create_instance(array('duedate'=>$now + 160,
 515                                                 'alwaysshowdescription'=>false,
 516                                                 'allowsubmissionsfromdate'=>$now + 60,
 517                                                 'intro'=>'Some text'));
 518  
 519          // Get the event from the calendar.
 520          $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
 521          $event = $DB->get_record('event', $params);
 522  
 523          $this->assertEmpty($event->description);
 524  
 525          // Change the allowsubmissionfromdate to the past - do this directly in the DB
 526          // because if we call the assignment update method - it will update the calendar
 527          // and we want to test that this works from cron.
 528          $DB->set_field('assign', 'allowsubmissionsfromdate', $now - 60, array('id'=>$assign->get_instance()->id));
 529          // Run cron to update the event in the calendar.
 530          assign::cron();
 531          $event = $DB->get_record('event', $params);
 532  
 533          $this->assertContains('Some text', $event->description);
 534  
 535      }
 536  
 537      public function test_update_instance() {
 538          global $DB;
 539  
 540          $this->setUser($this->editingteachers[0]);
 541          $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
 542  
 543          $now = time();
 544          $instance = $assign->get_instance();
 545          $instance->duedate = $now;
 546          $instance->instance = $instance->id;
 547          $instance->assignsubmission_onlinetext_enabled = 1;
 548  
 549          $assign->update_instance($instance);
 550  
 551          $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
 552          $this->assertEquals($now, $instance->duedate);
 553      }
 554  
 555      public function test_cannot_submit_empty() {
 556          global $PAGE;
 557  
 558          $this->setUser($this->editingteachers[0]);
 559          $assign = $this->create_instance(array('submissiondrafts'=>1));
 560  
 561          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
 562  
 563          // Test you cannot see the submit button for an offline assignment regardless.
 564          $this->setUser($this->students[0]);
 565          $output = $assign->view_student_summary($this->students[0], true);
 566          $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Can submit empty offline assignment');
 567  
 568          // Test you cannot see the submit button for an online text assignment with no submission.
 569          $this->setUser($this->editingteachers[0]);
 570          $instance = $assign->get_instance();
 571          $instance->instance = $instance->id;
 572          $instance->assignsubmission_onlinetext_enabled = 1;
 573  
 574          $assign->update_instance($instance);
 575          $this->setUser($this->students[0]);
 576          $output = $assign->view_student_summary($this->students[0], true);
 577          $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Cannot submit empty onlinetext assignment');
 578  
 579          // Simulate a submission.
 580          $submission = $assign->get_user_submission($this->students[0]->id, true);
 581          $data = new stdClass();
 582          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 583                                           'text'=>'Submission text',
 584                                           'format'=>FORMAT_MOODLE);
 585          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 586          $plugin->save($submission, $data);
 587          // Test you can see the submit button for an online text assignment with a submission.
 588          $output = $assign->view_student_summary($this->students[0], true);
 589          $this->assertContains(get_string('submitassignment', 'assign'), $output, 'Can submit non empty onlinetext assignment');
 590      }
 591  
 592      public function test_list_participants() {
 593          global $CFG, $DB;
 594  
 595          $this->create_extra_users();
 596          $this->setUser($this->editingteachers[0]);
 597          $assign = $this->create_instance(array('grade'=>100));
 598  
 599          $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
 600  
 601          // Teacher with user preference set should see suspended users as well.
 602          set_user_preference('grade_report_showonlyactiveenrol', false);
 603          $assign = $this->create_instance(array('grade'=>100));
 604          $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT,
 605                  count($assign->list_participants(null, true)));
 606  
 607          // Non-editing teacher should not see suspended users, even if user preference is set.
 608          $this->setUser($this->teachers[0]);
 609          set_user_preference('grade_report_showonlyactiveenrol', false);
 610          $assign = $this->create_instance(array('grade'=>100));
 611          $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
 612  
 613          // Turn on availability and a group restriction, and check that it doesn't
 614          // show users who aren't in the group.
 615          $CFG->enableavailability = true;
 616          $specialgroup = $this->getDataGenerator()->create_group(
 617                  array('courseid' => $this->course->id));
 618          $assign = $this->create_instance(array('grade' => 100,
 619                  'availability' => json_encode(\core_availability\tree::get_root_json(
 620                      array(\availability_group\condition::get_json($specialgroup->id))))));
 621          groups_add_member($specialgroup, $this->students[0]);
 622          groups_add_member($specialgroup, $this->students[1]);
 623          $this->assertEquals(2, count($assign->list_participants(null, true)));
 624      }
 625  
 626      public function test_count_teams() {
 627          $this->create_extra_users();
 628          $this->setUser($this->editingteachers[0]);
 629          $assign = $this->create_instance(array('teamsubmission'=>1));
 630  
 631          $this->assertEquals(self::GROUP_COUNT + 1, $assign->count_teams());
 632      }
 633  
 634      public function test_submit_to_default_group() {
 635          global $DB;
 636  
 637          $this->preventResetByRollback();
 638          $sink = $this->redirectMessages();
 639  
 640          $this->setUser($this->editingteachers[0]);
 641          $params = array('teamsubmission' => 1,
 642                          'assignsubmission_onlinetext_enabled' => 1,
 643                          'submissiondrafts'=>0);
 644          $assign = $this->create_instance($params);
 645  
 646          $newstudent = $this->getDataGenerator()->create_user();
 647          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 648          $this->getDataGenerator()->enrol_user($newstudent->id,
 649                                                $this->course->id,
 650                                                $studentrole->id);
 651          $this->setUser($newstudent);
 652          $data = new stdClass();
 653          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 654                                           'text'=>'Submission text',
 655                                           'format'=>FORMAT_MOODLE);
 656          $notices = array();
 657  
 658          $group = $assign->get_submission_group($newstudent->id);
 659          $this->assertFalse($group, 'New student is in default group');
 660          $assign->save_submission($data, $notices);
 661          $this->assertEmpty($notices, 'No errors on save submission');
 662  
 663          $sink->close();
 664      }
 665  
 666      public function test_count_submissions() {
 667          $this->create_extra_users();
 668          $this->setUser($this->editingteachers[0]);
 669          $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
 670  
 671          // Simulate a submission.
 672          $this->setUser($this->extrastudents[0]);
 673          $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
 674          $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
 675          $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
 676          // Leave this one as DRAFT.
 677          $data = new stdClass();
 678          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 679                                           'text'=>'Submission text',
 680                                           'format'=>FORMAT_MOODLE);
 681          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 682          $plugin->save($submission, $data);
 683  
 684          // Simulate adding a grade.
 685          $this->setUser($this->teachers[0]);
 686          $data = new stdClass();
 687          $data->grade = '50.0';
 688          $assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0);
 689  
 690          // Simulate a submission.
 691          $this->setUser($this->extrastudents[1]);
 692          $submission = $assign->get_user_submission($this->extrastudents[1]->id, true);
 693          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 694          $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
 695          $data = new stdClass();
 696          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 697                                           'text'=>'Submission text',
 698                                           'format'=>FORMAT_MOODLE);
 699          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 700          $plugin->save($submission, $data);
 701  
 702          // Simulate a submission.
 703          $this->setUser($this->extrastudents[2]);
 704          $submission = $assign->get_user_submission($this->extrastudents[2]->id, true);
 705          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 706          $assign->testable_update_submission($submission, $this->extrastudents[2]->id, true, false);
 707          $data = new stdClass();
 708          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 709                                           'text'=>'Submission text',
 710                                           'format'=>FORMAT_MOODLE);
 711          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 712          $plugin->save($submission, $data);
 713  
 714          // Simulate a submission.
 715          $this->setUser($this->extrastudents[3]);
 716          $submission = $assign->get_user_submission($this->extrastudents[3]->id, true);
 717          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 718          $assign->testable_update_submission($submission, $this->extrastudents[3]->id, true, false);
 719          $data = new stdClass();
 720          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 721                                           'text'=>'Submission text',
 722                                           'format'=>FORMAT_MOODLE);
 723          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 724          $plugin->save($submission, $data);
 725  
 726          // Simulate a submission for suspended user, this will never be counted.
 727          $this->setUser($this->extrastudents[3]);
 728          $submission = $assign->get_user_submission($this->extrasuspendedstudents[0]->id, true);
 729          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 730          $assign->testable_update_submission($submission, $this->extrasuspendedstudents[0]->id, true, false);
 731          $data = new stdClass();
 732          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 733                                           'text'=>'Submission text',
 734                                           'format'=>FORMAT_MOODLE);
 735          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
 736          $plugin->save($submission, $data);
 737  
 738          // Simulate adding a grade.
 739          $this->setUser($this->teachers[0]);
 740          $data = new stdClass();
 741          $data->grade = '50.0';
 742          $assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0);
 743          $assign->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0);
 744  
 745          $this->assertEquals(2, $assign->count_grades());
 746          $this->assertEquals(4, $assign->count_submissions());
 747          $this->assertEquals(2, $assign->count_submissions_need_grading());
 748          $this->assertEquals(3, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
 749          $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
 750      }
 751  
 752      public function test_get_grading_userid_list() {
 753          $this->create_extra_users();
 754          $this->setUser($this->editingteachers[0]);
 755          $assign = $this->create_instance();
 756  
 757          $users = $assign->testable_get_grading_userid_list();
 758          $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($users));
 759  
 760          $this->setUser($this->editingteachers[0]);
 761          set_user_preference('grade_report_showonlyactiveenrol', false);
 762          $assign = $this->create_instance();
 763  
 764          $users = $assign->testable_get_grading_userid_list();
 765          $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT, count($users));
 766      }
 767  
 768      public function test_cron() {
 769          // First run cron so there are no messages waiting to be sent (from other tests).
 770          cron_setup_user();
 771          assign::cron();
 772  
 773          // Now create an assignment and add some feedback.
 774          $this->setUser($this->editingteachers[0]);
 775          $assign = $this->create_instance(array('sendstudentnotifications'=>1));
 776  
 777          // Simulate adding a grade.
 778          $this->setUser($this->teachers[0]);
 779          $data = new stdClass();
 780          $data->grade = '50.0';
 781          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
 782          $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
 783  
 784          $data->sendstudentnotifications = false;
 785          $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0);
 786  
 787          // Now run cron and see that one message was sent.
 788          $this->preventResetByRollback();
 789          $sink = $this->redirectMessages();
 790          cron_setup_user();
 791          $this->expectOutputRegex('/Done processing 2 assignment submissions/');
 792          assign::cron();
 793  
 794          $messages = $sink->get_messages();
 795          // The sent count should be 2, because the 3rd one was marked as do not send notifications.
 796          $this->assertEquals(2, count($messages));
 797          $this->assertEquals(1, $messages[0]->notification);
 798          $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
 799      }
 800  
 801      public function test_is_graded() {
 802          $this->setUser($this->editingteachers[0]);
 803          $assign = $this->create_instance();
 804  
 805          // Simulate adding a grade.
 806          $this->setUser($this->teachers[0]);
 807          $data = new stdClass();
 808          $data->grade = '50.0';
 809          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
 810  
 811          $this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id));
 812          $this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
 813      }
 814  
 815      public function test_can_grade() {
 816          global $DB;
 817  
 818          $this->setUser($this->editingteachers[0]);
 819          $assign = $this->create_instance();
 820  
 821          $this->setUser($this->students[0]);
 822          $this->assertEquals(false, $assign->can_grade());
 823          $this->setUser($this->editingteachers[0]);
 824          $this->assertEquals(true, $assign->can_grade());
 825          $this->setUser($this->teachers[0]);
 826          $this->assertEquals(true, $assign->can_grade());
 827  
 828          // Test the viewgrades capability - without mod/assign:grade.
 829          $this->setUser($this->students[0]);
 830          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 831          assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
 832          $this->assertEquals(false, $assign->can_grade());
 833      }
 834  
 835      public function test_can_view_submission() {
 836          global $DB;
 837  
 838          $this->create_extra_users();
 839          $this->setUser($this->editingteachers[0]);
 840          $assign = $this->create_instance();
 841  
 842          $this->setUser($this->students[0]);
 843          $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
 844          $this->assertEquals(false, $assign->can_view_submission($this->students[1]->id));
 845          $this->assertEquals(false, $assign->can_view_submission($this->teachers[0]->id));
 846          $this->setUser($this->teachers[0]);
 847          $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
 848          $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
 849          $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
 850          $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
 851          $this->setUser($this->editingteachers[0]);
 852          $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
 853          $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
 854          $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
 855          $this->assertEquals(true, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
 856  
 857          // Test the viewgrades capability - without mod/assign:grade.
 858          $this->setUser($this->students[0]);
 859          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 860          assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
 861          $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
 862          $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
 863          $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
 864          $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
 865      }
 866  
 867  
 868      public function test_update_submission() {
 869          $this->create_extra_users();
 870          $this->setUser($this->editingteachers[0]);
 871          $assign = $this->create_instance();
 872  
 873          $this->setUser($this->extrastudents[0]);
 874          $now = time();
 875          $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
 876          $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
 877  
 878          $this->setUser($this->teachers[0]);
 879          // Verify the gradebook update.
 880          $gradinginfo = grade_get_grades($this->course->id,
 881                                          'mod',
 882                                          'assign',
 883                                          $assign->get_instance()->id,
 884                                          $this->extrastudents[0]->id);
 885  
 886          $this->assertEquals($this->extrastudents[0]->id,
 887                              $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
 888  
 889          // Now verify group assignments.
 890          $this->setUser($this->editingteachers[0]);
 891          $assign = $this->create_instance(array('teamsubmission'=>1));
 892  
 893          $this->setUser($this->extrastudents[0]);
 894          $now = time();
 895          $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
 896          $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
 897  
 898          // Check that at least 2 active members and 1 suspended member of the submission group had their submission updated.
 899  
 900          $this->setUser($this->editingteachers[0]);
 901          $gradinginfo = grade_get_grades($this->course->id,
 902                                          'mod',
 903                                          'assign',
 904                                          $assign->get_instance()->id,
 905                                          $this->extrastudents[0]->id);
 906  
 907          $this->assertEquals($this->extrastudents[0]->id,
 908                              $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
 909  
 910          $gradinginfo = grade_get_grades($this->course->id,
 911                                          'mod',
 912                                          'assign',
 913                                          $assign->get_instance()->id,
 914                                          $this->extrastudents[self::GROUP_COUNT]->id);
 915  
 916          $this->assertEquals($this->extrastudents[self::GROUP_COUNT]->id,
 917                              $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT]->id]->usermodified);
 918  
 919          $gradinginfo = grade_get_grades($this->course->id,
 920                                          'mod',
 921                                          'assign',
 922                                          $assign->get_instance()->id,
 923                                          $this->extrasuspendedstudents[0]->id);
 924          $this->assertEquals($this->extrasuspendedstudents[0]->id,
 925                              $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[0]->id]->usermodified);
 926  
 927          // Check the same with non-editing teacher and make sure submission is not updated for suspended user.
 928          $this->setUser($this->editingteachers[0]);
 929          $assign = $this->create_instance(array('teamsubmission'=>1));
 930  
 931          $this->setUser($this->extrastudents[1]);
 932          $now = time();
 933          $submission = $assign->get_group_submission($this->extrastudents[1]->id, 0, true);
 934          $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, true);
 935  
 936          $this->setUser($this->teachers[0]);
 937          $gradinginfo = grade_get_grades($this->course->id,
 938                                          'mod',
 939                                          'assign',
 940                                          $assign->get_instance()->id,
 941                                          $this->extrastudents[1]->id);
 942  
 943          $this->assertEquals($this->extrastudents[1]->id,
 944                              $gradinginfo->items[0]->grades[$this->extrastudents[1]->id]->usermodified);
 945  
 946          $gradinginfo = grade_get_grades($this->course->id,
 947                                          'mod',
 948                                          'assign',
 949                                          $assign->get_instance()->id,
 950                                          $this->extrastudents[self::GROUP_COUNT+1]->id);
 951  
 952          $this->assertEquals($this->extrastudents[self::GROUP_COUNT+1]->id,
 953                              $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT+1]->id]->usermodified);
 954  
 955          $gradinginfo = grade_get_grades($this->course->id,
 956                                          'mod',
 957                                          'assign',
 958                                          $assign->get_instance()->id,
 959                                          $this->extrasuspendedstudents[1]->id);
 960          $this->assertEquals($this->extrasuspendedstudents[1]->id,
 961                              $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[1]->id]->usermodified);
 962  
 963          // Now verify blind marking.
 964          $this->setUser($this->editingteachers[0]);
 965          $assign = $this->create_instance(array('blindmarking'=>1));
 966  
 967          $this->setUser($this->extrastudents[0]);
 968          $now = time();
 969          $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
 970          $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
 971  
 972          $this->setUser($this->editingteachers[0]);
 973          $gradinginfo = grade_get_grades($this->course->id,
 974                                          'mod',
 975                                          'assign',
 976                                          $assign->get_instance()->id,
 977                                          $this->extrastudents[0]->id);
 978  
 979          $this->assertEquals(null, $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->datesubmitted);
 980      }
 981  
 982      public function test_group_submissions_submit_for_marking_requireallteammemberssubmit() {
 983          global $PAGE;
 984  
 985          $this->create_extra_users();
 986          // Now verify group assignments.
 987          $this->setUser($this->editingteachers[0]);
 988          $assign = $this->create_instance(array('teamsubmission'=>1,
 989                                                 'assignsubmission_onlinetext_enabled'=>1,
 990                                                 'submissiondrafts'=>1,
 991                                                 'requireallteammemberssubmit'=>1));
 992          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
 993  
 994          // Add a submission.
 995          $this->setUser($this->extrastudents[0]);
 996          $data = new stdClass();
 997          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
 998                                           'text'=>'Submission text',
 999                                           'format'=>FORMAT_MOODLE);
1000  
1001          $notices = array();
1002          $assign->save_submission($data, $notices);
1003  
1004          // Check we can see the submit button.
1005          $output = $assign->view_student_summary($this->extrastudents[0], true);
1006          $this->assertContains(get_string('submitassignment', 'assign'), $output);
1007  
1008          $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1009          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1010          $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
1011  
1012          // Check that the student does not see "Submit" button.
1013          $output = $assign->view_student_summary($this->extrastudents[0], true);
1014          $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1015  
1016          // Change to another user in the same group.
1017          $this->setUser($this->extrastudents[self::GROUP_COUNT]);
1018          $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1019          $this->assertContains(get_string('submitassignment', 'assign'), $output);
1020  
1021          $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
1022          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1023          $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
1024          $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1025          $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1026      }
1027  
1028      public function test_group_submissions_submit_for_marking() {
1029          global $PAGE;
1030  
1031          $this->create_extra_users();
1032          // Now verify group assignments.
1033          $this->setUser($this->editingteachers[0]);
1034          $time = time();
1035          $assign = $this->create_instance(array('teamsubmission'=>1,
1036                                                 'assignsubmission_onlinetext_enabled'=>1,
1037                                                 'submissiondrafts'=>1,
1038                                                 'requireallteammemberssubmit'=>0,
1039                                                 'duedate' => $time - 2*24*60*60));
1040          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1041  
1042          $this->setUser($this->extrastudents[0]);
1043          // Add a submission.
1044          $data = new stdClass();
1045          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1046                                           'text'=>'Submission text',
1047                                           'format'=>FORMAT_MOODLE);
1048  
1049          $notices = array();
1050          $assign->save_submission($data, $notices);
1051  
1052          // Check we can see the submit button.
1053          $output = $assign->view_student_summary($this->extrastudents[0], true);
1054          $this->assertContains(get_string('submitassignment', 'assign'), $output);
1055          $this->assertContains(get_string('timeremaining', 'assign'), $output);
1056          $difftime = time() - $time;
1057          $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60 + $difftime)), $output);
1058  
1059          $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1060          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1061          $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
1062  
1063          // Check that the student does not see "Submit" button.
1064          $output = $assign->view_student_summary($this->extrastudents[0], true);
1065          $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1066  
1067          // Change to another user in the same group.
1068          $this->setUser($this->extrastudents[self::GROUP_COUNT]);
1069          $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1070          $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1071  
1072          // Check that time remaining is not overdue.
1073          $this->assertContains(get_string('timeremaining', 'assign'), $output);
1074          $difftime = time() - $time;
1075          $this->assertContains(get_string('submittedlate', 'assign', format_time(2*24*60*60 + $difftime)), $output);
1076  
1077          $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
1078          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1079          $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
1080          $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1081          $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1082      }
1083  
1084      public function test_submissions_open() {
1085          $this->setUser($this->editingteachers[0]);
1086  
1087          $now = time();
1088          $tomorrow = $now + 24*60*60;
1089          $oneweek = $now + 7*24*60*60;
1090          $yesterday = $now - 24*60*60;
1091  
1092          $assign = $this->create_instance();
1093          $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1094  
1095          $assign = $this->create_instance(array('duedate'=>$tomorrow));
1096          $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1097  
1098          $assign = $this->create_instance(array('duedate'=>$yesterday));
1099          $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1100  
1101          $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$tomorrow));
1102          $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1103  
1104          $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$yesterday));
1105          $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
1106  
1107          $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
1108          $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1109  
1110          $assign = $this->create_instance(array('submissiondrafts'=>1));
1111          $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1112  
1113          $this->setUser($this->students[0]);
1114          $now = time();
1115          $submission = $assign->get_user_submission($this->students[0]->id, true);
1116          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1117          $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1118          $this->setUser($this->editingteachers[0]);
1119          $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
1120      }
1121  
1122      public function test_get_graders() {
1123          $this->create_extra_users();
1124          $this->setUser($this->editingteachers[0]);
1125  
1126          // Create an assignment with no groups.
1127          $assign = $this->create_instance();
1128          $this->assertCount(self::DEFAULT_TEACHER_COUNT +
1129                             self::DEFAULT_EDITING_TEACHER_COUNT +
1130                             self::EXTRA_TEACHER_COUNT +
1131                             self::EXTRA_EDITING_TEACHER_COUNT,
1132                             $assign->testable_get_graders($this->students[0]->id));
1133  
1134          // Force create an assignment with SEPARATEGROUPS.
1135          $data = new stdClass();
1136          $data->courseid = $this->course->id;
1137          $data->name = 'Grouping';
1138          $groupingid = groups_create_grouping($data);
1139          groups_assign_grouping($groupingid, $this->groups[0]->id);
1140          $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
1141  
1142          $this->setUser($this->students[1]);
1143          $this->assertCount(4, $assign->testable_get_graders($this->students[0]->id));
1144          // Note the second student is in a group that is not in the grouping.
1145          // This means that we get all graders that are not in a group in the grouping.
1146          $this->assertCount(10, $assign->testable_get_graders($this->students[1]->id));
1147      }
1148  
1149      public function test_get_notified_users() {
1150          global $CFG, $DB;
1151  
1152          $capability = 'mod/assign:receivegradernotifications';
1153          $coursecontext = context_course::instance($this->course->id);
1154          $role = $DB->get_record('role', array('shortname' => 'teacher'));
1155  
1156          $this->create_extra_users();
1157          $this->setUser($this->editingteachers[0]);
1158  
1159          // Create an assignment with no groups.
1160          $assign = $this->create_instance();
1161  
1162          $this->assertCount(self::DEFAULT_TEACHER_COUNT +
1163                             self::DEFAULT_EDITING_TEACHER_COUNT +
1164                             self::EXTRA_TEACHER_COUNT +
1165                             self::EXTRA_EDITING_TEACHER_COUNT,
1166                             $assign->testable_get_notifiable_users($this->students[0]->id));
1167  
1168          // Change nonediting teachers role to not receive grader notifications.
1169          assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
1170  
1171          $this->assertCount(self::DEFAULT_EDITING_TEACHER_COUNT +
1172                             self::EXTRA_EDITING_TEACHER_COUNT,
1173                             $assign->testable_get_notifiable_users($this->students[0]->id));
1174  
1175          // Reset nonediting teachers role to default.
1176          unassign_capability($capability, $role->id, $coursecontext);
1177  
1178          // Force create an assignment with SEPARATEGROUPS.
1179          $data = new stdClass();
1180          $data->courseid = $this->course->id;
1181          $data->name = 'Grouping';
1182          $groupingid = groups_create_grouping($data);
1183          groups_assign_grouping($groupingid, $this->groups[0]->id);
1184          $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
1185  
1186          $this->setUser($this->students[1]);
1187          $this->assertCount(4, $assign->testable_get_notifiable_users($this->students[0]->id));
1188          // Note the second student is in a group that is not in the grouping.
1189          // This means that we get all graders that are not in a group in the grouping.
1190          $this->assertCount(10, $assign->testable_get_notifiable_users($this->students[1]->id));
1191  
1192          // Change nonediting teachers role to not receive grader notifications.
1193          assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
1194  
1195          $this->assertCount(2, $assign->testable_get_notifiable_users($this->students[0]->id));
1196          // Note the second student is in a group that is not in the grouping.
1197          // This means that we get all graders that are not in a group in the grouping.
1198          $this->assertCount(5, $assign->testable_get_notifiable_users($this->students[1]->id));
1199      }
1200  
1201      public function test_group_members_only() {
1202          global $CFG;
1203  
1204          $this->setAdminUser();
1205          $this->create_extra_users();
1206          $CFG->enableavailability = true;
1207          $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id));
1208          groups_assign_grouping($grouping->id, $this->groups[0]->id);
1209  
1210          // Force create an assignment with SEPARATEGROUPS.
1211          $instance = $this->getDataGenerator()->create_module('assign', array('course'=>$this->course->id),
1212                  array('availability' => json_encode(\core_availability\tree::get_root_json(array(
1213                      \availability_grouping\condition::get_json()))),
1214                  'groupingid' => $grouping->id));
1215  
1216          $cm = get_coursemodule_from_instance('assign', $instance->id);
1217          $context = context_module::instance($cm->id);
1218          $assign = new testable_assign($context, $cm, $this->course);
1219  
1220          $this->setUser($this->teachers[0]);
1221          get_fast_modinfo($this->course, 0, true);
1222          $this->assertCount(5, $assign->list_participants(0, true));
1223  
1224      }
1225  
1226      public function test_get_uniqueid_for_user() {
1227          $this->setUser($this->editingteachers[0]);
1228          $assign = $this->create_instance();
1229  
1230          foreach ($this->students as $student) {
1231              $uniqueid = $assign->get_uniqueid_for_user($student->id);
1232              $this->assertEquals($student->id, $assign->get_user_id_for_uniqueid($uniqueid));
1233          }
1234      }
1235  
1236      public function test_show_student_summary() {
1237          global $CFG, $PAGE;
1238  
1239          $this->setUser($this->editingteachers[0]);
1240          $assign = $this->create_instance();
1241          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1242  
1243          // No feedback should be available because this student has not been graded.
1244          $this->setUser($this->students[0]);
1245          $output = $assign->view_student_summary($this->students[0], true);
1246          $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if there is no grade');
1247          // Simulate adding a grade.
1248          $this->setUser($this->teachers[0]);
1249          $data = new stdClass();
1250          $data->grade = '50.0';
1251          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1252  
1253          // Now we should see the feedback.
1254          $this->setUser($this->students[0]);
1255          $output = $assign->view_student_summary($this->students[0], true);
1256          $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback if there is a grade');
1257  
1258          // Now hide the grade in gradebook.
1259          $this->setUser($this->teachers[0]);
1260          require_once($CFG->libdir.'/gradelib.php');
1261          $gradeitem = new grade_item(array(
1262              'itemtype'      => 'mod',
1263              'itemmodule'    => 'assign',
1264              'iteminstance'  => $assign->get_instance()->id,
1265              'courseid'      => $this->course->id));
1266  
1267          $gradeitem->set_hidden(1, false);
1268  
1269          // No feedback should be available because the grade is hidden.
1270          $this->setUser($this->students[0]);
1271          $output = $assign->view_student_summary($this->students[0], true);
1272          $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
1273  
1274          // Do the same but add feedback.
1275          $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
1276  
1277          $this->setUser($this->teachers[0]);
1278          $grade = $assign->get_user_grade($this->students[0]->id, true);
1279          $data = new stdClass();
1280          $data->assignfeedbackcomments_editor = array('text'=>'Tomato sauce',
1281                                           'format'=>FORMAT_MOODLE);
1282          $plugin = $assign->get_feedback_plugin_by_type('comments');
1283          $plugin->save($grade, $data);
1284  
1285          // Should have feedback but no grade.
1286          $this->setUser($this->students[0]);
1287          $output = $assign->view_student_summary($this->students[0], true);
1288          $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback even if there is no grade');
1289          $this->assertEquals(false, strpos($output, 'Grade'), 'Do not show grade when there is no grade.');
1290          $this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.');
1291  
1292          // Now hide the grade in gradebook.
1293          $this->setUser($this->teachers[0]);
1294          $gradeitem = new grade_item(array(
1295              'itemtype'      => 'mod',
1296              'itemmodule'    => 'assign',
1297              'iteminstance'  => $assign->get_instance()->id,
1298              'courseid'      => $this->course->id));
1299  
1300          $gradeitem->set_hidden(1, false);
1301  
1302          // No feedback should be available because the grade is hidden.
1303          $this->setUser($this->students[0]);
1304          $output = $assign->view_student_summary($this->students[0], true);
1305          $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
1306      }
1307  
1308      public function test_attempt_reopen_method_manual() {
1309          global $PAGE;
1310  
1311          $this->setUser($this->editingteachers[0]);
1312          $assign = $this->create_instance(array('attemptreopenmethod'=>ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
1313                                                 'maxattempts'=>3,
1314                                                 'submissiondrafts'=>1,
1315                                                 'assignsubmission_onlinetext_enabled'=>1));
1316          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1317  
1318          // Student should be able to see an add submission button.
1319          $this->setUser($this->students[0]);
1320          $output = $assign->view_student_summary($this->students[0], true);
1321          $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1322  
1323          // Add a submission.
1324          $now = time();
1325          $submission = $assign->get_user_submission($this->students[0]->id, true);
1326          $data = new stdClass();
1327          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1328                                           'text'=>'Submission text',
1329                                           'format'=>FORMAT_MOODLE);
1330          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1331          $plugin->save($submission, $data);
1332  
1333          // And now submit it for marking.
1334          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1335          $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1336  
1337          // Verify the student cannot make changes to the submission.
1338          $output = $assign->view_student_summary($this->students[0], true);
1339          $this->assertEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1340  
1341          // Mark the submission.
1342          $this->setUser($this->teachers[0]);
1343          $data = new stdClass();
1344          $data->grade = '50.0';
1345          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1346  
1347          // Check the student can see the grade.
1348          $this->setUser($this->students[0]);
1349          $output = $assign->view_student_summary($this->students[0], true);
1350          $this->assertNotEquals(false, strpos($output, '50.0'));
1351  
1352          // Allow the student another attempt.
1353          $this->teachers[0]->ignoresesskey = true;
1354          $this->setUser($this->teachers[0]);
1355          $result = $assign->testable_process_add_attempt($this->students[0]->id);
1356          $this->assertEquals(true, $result);
1357  
1358          // Check that the previous attempt is now in the submission history table.
1359          $this->setUser($this->students[0]);
1360          $output = $assign->view_student_summary($this->students[0], true);
1361          // Need a better check.
1362          $this->assertNotEquals(false, strpos($output, 'Submission text'), 'Contains: Submission text');
1363  
1364          // Check that the student now has a button for Add a new attempt".
1365          $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1366          // Check that the student now does not have a button for Submit.
1367          $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign')));
1368  
1369          // Check that the student now has a submission history.
1370          $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign')));
1371  
1372          $this->setUser($this->teachers[0]);
1373          // Check that the grading table loads correctly and contains this user.
1374          // This is also testing that we do not get duplicate rows in the grading table.
1375          $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1376          $output = $assign->get_renderer()->render($gradingtable);
1377          $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
1378  
1379          // Should be 1 not 2.
1380          $this->assertEquals(1, $assign->count_submissions());
1381          $this->assertEquals(1, $assign->count_submissions_with_status('reopened'));
1382          $this->assertEquals(0, $assign->count_submissions_need_grading());
1383          $this->assertEquals(1, $assign->count_grades());
1384  
1385          // Change max attempts to unlimited.
1386          $formdata = clone($assign->get_instance());
1387          $formdata->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
1388          $formdata->instance = $formdata->id;
1389          $assign->update_instance($formdata);
1390  
1391          // Mark the submission again.
1392          $data = new stdClass();
1393          $data->grade = '60.0';
1394          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1);
1395  
1396          // Check the grade exists.
1397          $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1398          $this->assertEquals(60, (int)$grades[$this->students[0]->id]->rawgrade);
1399  
1400          // Check we can reopen still.
1401          $result = $assign->testable_process_add_attempt($this->students[0]->id);
1402          $this->assertEquals(true, $result);
1403  
1404          // Should no longer have a grade because there is no grade for the latest attempt.
1405          $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1406          $this->assertEmpty($grades);
1407  
1408      }
1409  
1410      public function test_markingworkflow() {
1411          global $PAGE;
1412  
1413          $this->setUser($this->editingteachers[0]);
1414          $assign = $this->create_instance(array('markingworkflow'=>1));
1415          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1416  
1417          // Mark the submission and set to notmarked.
1418          $this->setUser($this->teachers[0]);
1419          $data = new stdClass();
1420          $data->grade = '50.0';
1421          $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED;
1422          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1423  
1424          // Check the student can't see the grade.
1425          $this->setUser($this->students[0]);
1426          $output = $assign->view_student_summary($this->students[0], true);
1427          $this->assertEquals(false, strpos($output, '50.0'));
1428  
1429          // Mark the submission and set to inmarking.
1430          $this->setUser($this->teachers[0]);
1431          $data = new stdClass();
1432          $data->grade = '50.0';
1433          $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INMARKING;
1434          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1435  
1436          // Check the student can't see the grade.
1437          $this->setUser($this->students[0]);
1438          $output = $assign->view_student_summary($this->students[0], true);
1439          $this->assertEquals(false, strpos($output, '50.0'));
1440  
1441          // Mark the submission and set to readyforreview.
1442          $this->setUser($this->teachers[0]);
1443          $data = new stdClass();
1444          $data->grade = '50.0';
1445          $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW;
1446          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1447  
1448          // Check the student can't see the grade.
1449          $this->setUser($this->students[0]);
1450          $output = $assign->view_student_summary($this->students[0], true);
1451          $this->assertEquals(false, strpos($output, '50.0'));
1452  
1453          // Mark the submission and set to inreview.
1454          $this->setUser($this->teachers[0]);
1455          $data = new stdClass();
1456          $data->grade = '50.0';
1457          $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW;
1458          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1459  
1460          // Check the student can't see the grade.
1461          $this->setUser($this->students[0]);
1462          $output = $assign->view_student_summary($this->students[0], true);
1463          $this->assertEquals(false, strpos($output, '50.0'));
1464  
1465          // Mark the submission and set to readyforrelease.
1466          $this->setUser($this->teachers[0]);
1467          $data = new stdClass();
1468          $data->grade = '50.0';
1469          $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE;
1470          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1471  
1472          // Check the student can't see the grade.
1473          $this->setUser($this->students[0]);
1474          $output = $assign->view_student_summary($this->students[0], true);
1475          $this->assertEquals(false, strpos($output, '50.0'));
1476  
1477          // Mark the submission and set to released.
1478          $this->setUser($this->teachers[0]);
1479          $data = new stdClass();
1480          $data->grade = '50.0';
1481          $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED;
1482          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1483  
1484          // Check the student can see the grade.
1485          $this->setUser($this->students[0]);
1486          $output = $assign->view_student_summary($this->students[0], true);
1487          $this->assertNotEquals(false, strpos($output, '50.0'));
1488      }
1489  
1490      public function test_markerallocation() {
1491          global $PAGE;
1492  
1493          $this->setUser($this->editingteachers[0]);
1494          $assign = $this->create_instance(array('markingworkflow'=>1, 'markingallocation'=>1));
1495          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1496  
1497          // Allocate marker to submission.
1498          $data = new stdClass();
1499          $data->allocatedmarker = $this->teachers[0]->id;
1500          $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1501  
1502          // Check the allocated marker can view the submission.
1503          $this->setUser($this->teachers[0]);
1504          $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1505          $output = $assign->get_renderer()->render($gradingtable);
1506          $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
1507  
1508          // Check that other teachers can't view this submission.
1509          $this->setUser($this->teachers[1]);
1510          $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1511          $output = $assign->get_renderer()->render($gradingtable);
1512          $this->assertNotEquals(true, strpos($output, $this->students[0]->lastname));
1513      }
1514  
1515  
1516  
1517      public function test_teacher_submit_for_student() {
1518          global $PAGE;
1519  
1520          $this->preventResetByRollback();
1521          $sink = $this->redirectMessages();
1522  
1523          $this->setUser($this->editingteachers[0]);
1524  
1525          $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1));
1526          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1527  
1528          $this->setUser($this->students[0]);
1529          // Simulate a submission.
1530          $data = new stdClass();
1531          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1532                                           'text'=>'Student submission text',
1533                                           'format'=>FORMAT_MOODLE);
1534  
1535          $notices = array();
1536          $assign->save_submission($data, $notices);
1537  
1538          // Check that the submission text was saved.
1539          $output = $assign->view_student_summary($this->students[0], true);
1540          $this->assertContains('Student submission text', $output, 'Contains student submission text');
1541  
1542          // Check that a teacher teacher with the extra capability can edit a students submission.
1543          $this->setUser($this->teachers[0]);
1544          $data = new stdClass();
1545          $data->userid = $this->students[0]->id;
1546          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1547                                           'text'=>'Teacher edited submission text',
1548                                           'format'=>FORMAT_MOODLE);
1549  
1550          // Add the required capability.
1551          $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
1552          assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
1553          role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id);
1554          accesslib_clear_all_caches_for_unit_testing();
1555  
1556          // Try to save the submission.
1557          $notices = array();
1558          $assign->save_submission($data, $notices);
1559  
1560          // Check that the teacher can submit the students work.
1561          $data = new stdClass();
1562          $data->userid = $this->students[0]->id;
1563          $notices = array();
1564          $assign->submit_for_grading($data, $notices);
1565  
1566          // Revert to draft so the student can edit it.
1567          $assign->revert_to_draft($this->students[0]->id);
1568  
1569          $this->setUser($this->students[0]);
1570  
1571          // Check that the submission text was saved.
1572          $output = $assign->view_student_summary($this->students[0], true);
1573          $this->assertContains('Teacher edited submission text', $output, 'Contains student submission text');
1574  
1575          // Check that the student can submit their work.
1576          $data = new stdClass();
1577          $assign->submit_for_grading($data, $notices);
1578  
1579          $output = $assign->view_student_summary($this->students[0], true);
1580          $this->assertNotContains(get_string('addsubmission', 'assign'), $output);
1581  
1582          // Set to a default editing teacher who should not be able to edit this submission.
1583          $this->setUser($this->editingteachers[1]);
1584  
1585          // Revert to draft so the submission is editable.
1586          $assign->revert_to_draft($this->students[0]->id);
1587  
1588          $data = new stdClass();
1589          $data->userid = $this->students[0]->id;
1590          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1591                                           'text'=>'Teacher 2 edited submission text',
1592                                           'format'=>FORMAT_MOODLE);
1593  
1594          $notices = array();
1595          $this->setExpectedException('moodle_exception');
1596          $assign->save_submission($data, $notices);
1597  
1598          $sink->close();
1599      }
1600  
1601      public function test_disable_submit_after_cutoff_date() {
1602          global $PAGE;
1603  
1604          $this->setUser($this->editingteachers[0]);
1605          $now = time();
1606          $tomorrow = $now + 24*60*60;
1607          $lastweek = $now - 7*24*60*60;
1608          $yesterday = $now - 24*60*60;
1609  
1610          $assign = $this->create_instance(array('duedate'=>$yesterday,
1611                                                 'cutoffdate'=>$tomorrow,
1612                                                 'assignsubmission_onlinetext_enabled'=>1));
1613          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1614  
1615          // Student should be able to see an add submission button.
1616          $this->setUser($this->students[0]);
1617          $output = $assign->view_student_summary($this->students[0], true);
1618          $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1619  
1620          // Add a submission but don't submit now.
1621          $submission = $assign->get_user_submission($this->students[0]->id, true);
1622          $data = new stdClass();
1623          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1624                                           'text'=>'Submission text',
1625                                           'format'=>FORMAT_MOODLE);
1626          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1627          $plugin->save($submission, $data);
1628  
1629          // Create another instance with cut-off and due-date already passed.
1630          $this->setUser($this->editingteachers[0]);
1631          $now = time();
1632          $assign = $this->create_instance(array('duedate'=>$lastweek,
1633                                                 'cutoffdate'=>$yesterday,
1634                                                 'assignsubmission_onlinetext_enabled'=>1));
1635  
1636          $this->setUser($this->students[0]);
1637          $output = $assign->view_student_summary($this->students[0], true);
1638          $this->assertNotContains($output, get_string('editsubmission', 'assign'),
1639                                   'Should not be able to edit after cutoff date.');
1640          $this->assertNotContains($output, get_string('submitassignment', 'assign'),
1641                                   'Should not be able to submit after cutoff date.');
1642      }
1643      /**
1644       * Testing for submission comment plugin settings
1645       */
1646      public function test_submission_comment_plugin_settings() {
1647          global $CFG;
1648  
1649          $commentconfig = false;
1650          if (!empty($CFG->usecomments)) {
1651              $commentconfig = $CFG->usecomments;
1652          }
1653  
1654          $CFG->usecomments = true;
1655          $assign = $this->create_instance();
1656          $plugin = $assign->get_submission_plugin_by_type('comments');
1657          $this->assertEquals(1, $plugin->is_enabled('enabled'));
1658  
1659          $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0));
1660          $plugin = $assign->get_submission_plugin_by_type('comments');
1661          $this->assertEquals(1, $plugin->is_enabled('enabled'));
1662  
1663          $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1));
1664          $plugin = $assign->get_submission_plugin_by_type('comments');
1665          $this->assertEquals(1, $plugin->is_enabled('enabled'));
1666  
1667          $CFG->usecomments = false;
1668          $assign = $this->create_instance();
1669          $plugin = $assign->get_submission_plugin_by_type('comments');
1670          $this->assertEquals(0, $plugin->is_enabled('enabled'));
1671  
1672          $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0));
1673          $plugin = $assign->get_submission_plugin_by_type('comments');
1674          $this->assertEquals(0, $plugin->is_enabled('enabled'));
1675  
1676          $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1));
1677          $plugin = $assign->get_submission_plugin_by_type('comments');
1678          $this->assertEquals(0, $plugin->is_enabled('enabled'));
1679  
1680          $CFG->usecomments = $commentconfig;
1681      }
1682  
1683      /**
1684       * Testing for comment inline settings
1685       */
1686      public function test_feedback_comment_commentinline() {
1687          global $CFG;
1688  
1689          $sourcetext = "Hello!
1690  
1691  I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness.
1692  
1693  URL outside a tag: https://moodle.org/logo/logo-240x60.gif
1694  Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif
1695  
1696  External link 1:<img src='https://moodle.org/logo/logo-240x60.gif' alt='Moodle'/>
1697  External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\"/>
1698  Internal link 1:<img src='@@PLUGINFILE@@/logo-240x60.gif' alt='Moodle'/>
1699  Internal link 2:<img alt=\"Moodle\" src=\"@@PLUGINFILE@@logo-240x60.gif\"/>
1700  Anchor link 1:<a href=\"@@PLUGINFILE@@logo-240x60.gif\" alt=\"bananas\">Link text</a>
1701  Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
1702  ";
1703  
1704          // Note the internal images have been stripped and the html is purified (quotes fixed in this case).
1705          $filteredtext = "Hello!
1706  
1707  I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness.
1708  
1709  URL outside a tag: https://moodle.org/logo/logo-240x60.gif
1710  Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif
1711  
1712  External link 1:<img src=\"https://moodle.org/logo/logo-240x60.gif\" alt=\"Moodle\" />
1713  External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\" />
1714  Internal link 1:
1715  Internal link 2:
1716  Anchor link 1:Link text
1717  Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
1718  ";
1719  
1720          $this->setUser($this->editingteachers[0]);
1721          $params = array('assignsubmission_onlinetext_enabled' => 1,
1722                          'assignfeedback_comments_enabled' => 1,
1723                          'assignfeedback_comments_commentinline' => 1);
1724          $assign = $this->create_instance($params);
1725  
1726          $this->setUser($this->students[0]);
1727          // Add a submission but don't submit now.
1728          $submission = $assign->get_user_submission($this->students[0]->id, true);
1729          $data = new stdClass();
1730  
1731          // Test the internal link is stripped, but the external one is not.
1732          $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1733                                           'text'=>$sourcetext,
1734                                           'format'=>FORMAT_MOODLE);
1735  
1736          $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1737          $plugin->save($submission, $data);
1738  
1739          $this->setUser($this->editingteachers[0]);
1740  
1741          $data = new stdClass();
1742          require_once($CFG->dirroot . '/mod/assign/gradeform.php');
1743          $pagination = array('userid'=>$this->students[0]->id,
1744                              'rownum'=>0,
1745                              'last'=>true,
1746                              'useridlistid'=>time(),
1747                              'attemptnumber'=>0);
1748          $formparams = array($assign, $data, $pagination);
1749          $mform = new mod_assign_grade_form(null, $formparams);
1750  
1751          $this->assertEquals($filteredtext, $data->assignfeedbackcomments_editor['text']);
1752      }
1753  
1754      /**
1755       * Testing for feedback comment plugin settings
1756       */
1757      public function test_feedback_plugin_settings() {
1758  
1759          $assign = $this->create_instance();
1760          $plugin = $assign->get_feedback_plugin_by_type('comments');
1761          $this->assertEquals(0, $plugin->is_enabled('enabled'));
1762  
1763          $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 0));
1764          $plugin = $assign->get_feedback_plugin_by_type('comments');
1765          $this->assertEquals(0, $plugin->is_enabled('enabled'));
1766  
1767          $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
1768          $plugin = $assign->get_feedback_plugin_by_type('comments');
1769          $this->assertEquals(1, $plugin->is_enabled('enabled'));
1770      }
1771  
1772      /**
1773       * Testing if gradebook feedback plugin is enabled.
1774       */
1775      public function test_is_gradebook_feedback_enabled() {
1776          $adminconfig = get_config('assign');
1777          $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;
1778  
1779          // Create assignment with gradebook feedback enabled and grade = 0.
1780          $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 1, 'grades' => 0));
1781  
1782          // Get gradebook feedback plugin.
1783          $gradebookplugintype = str_replace('assignfeedback_', '', $gradebookplugin);
1784          $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype);
1785          $this->assertEquals(1, $plugin->is_enabled('enabled'));
1786          $this->assertEquals(1, $assign->is_gradebook_feedback_enabled());
1787  
1788          // Create assignment with gradebook feedback disabled and grade = 0.
1789          $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 0, 'grades' => 0));
1790          $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype);
1791          $this->assertEquals(0, $plugin->is_enabled('enabled'));
1792      }
1793  
1794      /**
1795       * Testing can_edit_submission
1796       */
1797      public function test_can_edit_submission() {
1798          global $PAGE, $DB;
1799          $this->create_extra_users();
1800  
1801          $this->setAdminUser();
1802          // Create assignment (onlinetext).
1803          $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1));
1804          $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1805  
1806          // Check student can edit their own submission.
1807          $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->students[0]->id));
1808          // Check student cannot edit others submission.
1809          $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->students[1]->id));
1810  
1811          // Check teacher cannot (by default) edit a students submission.
1812          $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id));
1813  
1814          // Add the required capability to edit a student submission.
1815          $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
1816          assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
1817          role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id);
1818          accesslib_clear_all_caches_for_unit_testing();
1819          // Retest - should now have access.
1820          $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id));
1821  
1822          // Force create an assignment with SEPARATEGROUPS.
1823          $data = new stdClass();
1824          $data->courseid = $this->course->id;
1825          $data->name = 'Grouping';
1826          $groupingid = groups_create_grouping($data);
1827          groups_assign_grouping($groupingid, $this->groups[0]->id);
1828          groups_assign_grouping($groupingid, $this->groups[1]->id);
1829          $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
1830  
1831          // Add the capability to the new assignment for extra students 0 and 1.
1832          assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
1833          role_assign($roleid, $this->extrastudents[0]->id, $assign->get_context()->id);
1834          role_assign($roleid, $this->extrastudents[1]->id, $assign->get_context()->id);
1835          accesslib_clear_all_caches_for_unit_testing();
1836  
1837          // Verify the extra student does not have the capability to edit a submission not in their group.
1838          $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[1]->id));
1839          // Verify the extra student does have the capability to edit a submission in their group.
1840          $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[0]->id));
1841  
1842      }
1843  
1844      /**
1845       * Test if the view blind details capability works
1846       */
1847      public function test_can_view_blind_details() {
1848          global $PAGE, $DB;
1849          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1850          $managerrole = $DB->get_record('role', array('shortname' => 'manager'));
1851  
1852          $student = $this->students[0];// Get a student user.
1853          // Create a teacher. Shouldn't be able to view blind marking ID.
1854          $teacher = $this->getDataGenerator()->create_user();
1855  
1856          $this->getDataGenerator()->enrol_user($teacher->id,
1857                                                $this->course->id,
1858                                                $teacherrole->id);
1859  
1860          // Create a manager.. Should be able to view blind marking ID.
1861          $manager = $this->getDataGenerator()->create_user();
1862          $this->getDataGenerator()->enrol_user($manager->id,
1863                  $this->course->id,
1864                  $managerrole->id);
1865  
1866          // Generate blind marking assignment.
1867          $assign = $this->create_instance(array('blindmarking' => 1));
1868          $this->assertEquals(true, $assign->is_blind_marking());
1869  
1870          // Test student names are hidden to teacher.
1871          $this->setUser($teacher);
1872          $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
1873          $output = $assign->get_renderer()->render($gradingtable);
1874          $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign')));    // "Participant" is somewhere on the page.
1875          $this->assertEquals(false, strpos($output, fullname($student)));    // Students full name doesn't appear.
1876  
1877          // Test student names are visible to manager.
1878          $this->setUser($manager);
1879          $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
1880          $output = $assign->get_renderer()->render($gradingtable);
1881          $this->assertEquals(false, strpos($output, get_string('hiddenuser', 'assign')));
1882          $this->assertEquals(true, strpos($output, fullname($student)));    //students full name doesn't appear.
1883      }
1884  }
1885  


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1