2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Unit tests for (some of) mod/assign/locallib.php.
22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die();
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');
35 * Unit tests for (some of) mod/assign/locallib.php.
37 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 class mod_assign_locallib_testcase extends mod_assign_base_testcase {
42 public function test_return_links() {
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());
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'));
59 foreach ($assign->get_feedback_plugins() as $plugin) {
60 $this->assertContains($plugin->get_type(), $installedplugins, 'Feedback plugin not in list of installed plugins');
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'));
69 foreach ($assign->get_submission_plugins() as $plugin) {
70 $this->assertContains($plugin->get_type(), $installedplugins, 'Submission plugin not in list of installed plugins');
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());
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')));
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;
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;
100 // Test sesskey is required.
101 $this->setUser($this->editingteachers[0]);
102 $this->setExpectedException('moodle_exception');
103 $assign->reveal_identities();
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;
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')));
117 // Set this back to default.
118 $this->editingteachers[0]->ignoresesskey = false;
122 * Test submissions with extension date.
124 public function test_gradingtable_extension_due_date() {
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,
134 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
135 'id' => $assign->get_course_module()->id,
136 'action' => 'grading',
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);
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);
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);
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);
174 * Test that late submissions with extension date calculate correctly.
176 public function test_gradingtable_extension_date_calculation_for_lateness() {
179 // Setup the assignment.
180 $this->create_extra_users();
181 $this->setUser($this->editingteachers[0]);
182 $assign = $this->create_instance(array(
183 'assignsubmission_onlinetext_enabled'=>1,
184 'duedate' => time() - 4 * 24 * 60 * 60,
186 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
187 'id' => $assign->get_course_module()->id,
188 'action' => 'grading',
191 // Check that the assignment is late.
192 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
193 $output = $assign->get_renderer()->render($gradingtable);
194 $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
195 $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60)), $output);
197 // Grant an extension that is in the past.
198 $assign->testable_save_user_extension($this->students[0]->id, time() - 2 * 24 * 60 * 60);
199 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
200 $output = $assign->get_renderer()->render($gradingtable);
201 $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
202 $this->assertContains(get_string('userextensiondate', 'assign', userdate(time() - 2*24*60*60)), $output);
203 $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60)), $output);
205 // Simulate a submission.
206 $this->setUser($this->students[0]);
207 $submission = $assign->get_user_submission($this->students[0]->id, true);
208 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
209 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
210 $data = new stdClass();
211 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
212 'text'=>'Submission text',
213 'format'=>FORMAT_MOODLE);
214 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
215 $plugin->save($submission, $data);
218 $this->setUser($this->editingteachers[0]);
219 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
220 $output = $assign->get_renderer()->render($gradingtable);
221 $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output);
222 $this->assertContains(get_string('userextensiondate', 'assign', userdate(time() - 2*24*60*60)), $output);
223 $this->assertContains(get_string('submittedlateshort', 'assign', format_time(2*24*60*60)), $output);
227 * Check that group submission information is rendered correctly in the
230 public function test_gradingtable_group_submissions_rendering() {
233 $this->create_extra_users();
234 // Now verify group assignments.
235 $this->setUser($this->teachers[0]);
236 $assign = $this->create_instance(array(
237 'teamsubmission' => 1,
238 'assignsubmission_onlinetext_enabled' => 1,
239 'submissiondrafts' => 1,
240 'requireallteammemberssubmit' => 0,
242 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
243 'id' => $assign->get_course_module()->id,
244 'action' => 'grading',
248 $this->setUser($this->extrastudents[0]);
249 $data = new stdClass();
250 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
251 'text'=>'Submission text',
252 'format'=>FORMAT_MOODLE);
254 $assign->save_submission($data, $notices);
256 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
257 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
258 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
261 $this->setUser($this->teachers[0]);
262 $gradingtable = new assign_grading_table($assign, 4, '', 0, true);
263 $output = $assign->get_renderer()->render($gradingtable);
264 $document = new DOMDocument();
265 $document->loadHTML($output);
266 $xpath = new DOMXPath($document);
269 $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c4"]/div[@class="submissionstatussubmitted"])'));
270 $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c4"]/div[@class="submissionstatussubmitted"])'));
272 // Check submission last modified date
273 $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])')));
274 $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c8"])')));
277 $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c5"])'));
278 $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c5"])'));
280 // Check submission text.
281 $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c9"]/div/div)'));
282 $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c9"]/div/div)'));
284 // Check comments can be made.
285 $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r0_c10"]//textarea)'));
286 $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r3_c10"]//textarea)'));
289 public function test_show_intro() {
290 // Test whether we are showing the intro at the correct times.
291 $this->setUser($this->editingteachers[0]);
292 $assign = $this->create_instance(array('alwaysshowdescription'=>1));
294 $this->assertEquals(true, $assign->testable_show_intro());
296 $tomorrow = time() + (24*60*60);
298 $assign = $this->create_instance(array('alwaysshowdescription'=>0,
299 'allowsubmissionsfromdate'=>$tomorrow));
300 $this->assertEquals(false, $assign->testable_show_intro());
301 $yesterday = time() - (24*60*60);
302 $assign = $this->create_instance(array('alwaysshowdescription'=>0,
303 'allowsubmissionsfromdate'=>$yesterday));
304 $this->assertEquals(true, $assign->testable_show_intro());
307 public function test_has_submissions_or_grades() {
308 $this->setUser($this->editingteachers[0]);
309 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
311 $instance = $assign->get_instance();
313 // Should start empty.
314 $this->assertEquals(false, $assign->has_submissions_or_grades());
316 // Simulate a submission.
317 $this->setUser($this->students[0]);
318 $submission = $assign->get_user_submission($this->students[0]->id, true);
319 $data = new stdClass();
320 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
321 'text'=>'Submission text',
322 'format'=>FORMAT_MOODLE);
323 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
324 $plugin->save($submission, $data);
327 $this->assertEquals(true, $assign->has_submissions_or_grades());
328 // Set this back to default.
329 $this->students[0]->ignoresesskey = false;
332 public function test_delete_grades() {
333 $this->setUser($this->editingteachers[0]);
334 $assign = $this->create_instance();
336 // Simulate adding a grade.
337 $this->setUser($this->teachers[0]);
338 $data = new stdClass();
339 $data->grade = '50.0';
340 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
342 // Now see if the data is in the gradebook.
343 $gradinginfo = grade_get_grades($this->course->id,
346 $assign->get_instance()->id);
348 $this->assertNotEquals(0, count($gradinginfo->items));
350 $assign->testable_delete_grades();
351 $gradinginfo = grade_get_grades($this->course->id,
354 $assign->get_instance()->id);
356 $this->assertEquals(0, count($gradinginfo->items));
359 public function test_delete_instance() {
360 $this->setUser($this->editingteachers[0]);
361 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
363 // Simulate adding a grade.
364 $this->setUser($this->teachers[0]);
365 $data = new stdClass();
366 $data->grade = '50.0';
367 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
369 // Simulate a submission.
370 $this->setUser($this->students[0]);
371 $submission = $assign->get_user_submission($this->students[0]->id, true);
372 $data = new stdClass();
373 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
374 'text'=>'Submission text',
375 'format'=>FORMAT_MOODLE);
376 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
377 $plugin->save($submission, $data);
379 // Now try and delete.
380 $this->assertEquals(true, $assign->delete_instance());
383 public function test_reset_userdata() {
387 $this->setUser($this->editingteachers[0]);
388 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1,
391 // Simulate adding a grade.
392 $this->setUser($this->teachers[0]);
393 $data = new stdClass();
394 $data->grade = '50.0';
395 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
397 // Simulate a submission.
398 $this->setUser($this->students[0]);
399 $submission = $assign->get_user_submission($this->students[0]->id, true);
400 $data = new stdClass();
401 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
402 'text'=>'Submission text',
403 'format'=>FORMAT_MOODLE);
404 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
405 $plugin->save($submission, $data);
407 $this->assertEquals(true, $assign->has_submissions_or_grades());
408 // Now try and reset.
409 $data = new stdClass();
410 $data->reset_assign_submissions = 1;
411 $data->reset_gradebook_grades = 1;
412 $data->courseid = $this->course->id;
413 $data->timeshift = 24*60*60;
414 $this->setUser($this->editingteachers[0]);
415 $assign->reset_userdata($data);
416 $this->assertEquals(false, $assign->has_submissions_or_grades());
418 // Reload the instance data.
419 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
420 $this->assertEquals($now + 24*60*60, $instance->duedate);
422 // Test reset using assign_reset_userdata().
423 $assignduedate = $instance->duedate; // Keep old updated value for comparison.
424 $data->timeshift = 2*24*60*60;
425 assign_reset_userdata($data);
426 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
427 $this->assertEquals($assignduedate + 2*24*60*60, $instance->duedate);
429 // Create one more assignment and reset, make sure time shifted for previous assignment is not changed.
430 $assign2 = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1,
432 $assignduedate = $instance->duedate;
433 $data->timeshift = 3*24*60*60;
434 $assign2->reset_userdata($data);
435 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
436 $this->assertEquals($assignduedate, $instance->duedate);
437 $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id));
438 $this->assertEquals($now + 3*24*60*60, $instance2->duedate);
440 // Reset both assignments using assign_reset_userdata() and make sure both assignments have same date.
441 $assignduedate = $instance->duedate;
442 $assign2duedate = $instance2->duedate;
443 $data->timeshift = 4*24*60*60;
444 assign_reset_userdata($data);
445 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
446 $this->assertEquals($assignduedate + 4*24*60*60, $instance->duedate);
447 $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id));
448 $this->assertEquals($assign2duedate + 4*24*60*60, $instance2->duedate);
451 public function test_plugin_settings() {
455 $this->setUser($this->editingteachers[0]);
456 $assign = $this->create_instance(array('assignsubmission_file_enabled'=>1,
457 'assignsubmission_file_maxfiles'=>12,
458 'assignsubmission_file_maxsizebytes'=>10));
460 $plugin = $assign->get_submission_plugin_by_type('file');
461 $this->assertEquals('12', $plugin->get_config('maxfilesubmissions'));
464 public function test_update_calendar() {
467 $this->setUser($this->editingteachers[0]);
468 $userctx = context_user::instance($this->editingteachers[0]->id)->id;
470 // Hack to pretend that there was an editor involved. We need both $_POST and $_REQUEST, and a sesskey.
471 $draftid = file_get_unused_draft_itemid();
472 $_REQUEST['introeditor'] = $draftid;
473 $_POST['introeditor'] = $draftid;
474 $_POST['sesskey'] = sesskey();
476 // Write links to a draft area.
477 $fakearealink1 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">link</a>', 'draftfile.php', $userctx,
478 'user', 'draft', $draftid);
479 $fakearealink2 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">new</a>', 'draftfile.php', $userctx,
480 'user', 'draft', $draftid);
482 // Create a new assignment with links to a draft area.
484 $assign = $this->create_instance(array(
486 'intro' => $fakearealink1,
487 'introformat' => FORMAT_HTML
490 // See if there is an event in the calendar.
491 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
492 $event = $DB->get_record('event', $params);
493 $this->assertNotEmpty($event);
494 $this->assertSame('link', $event->description); // The pluginfile links are removed.
496 // Make sure the same works when updating the assignment.
497 $instance = $assign->get_instance();
498 $instance->instance = $instance->id;
499 $instance->intro = $fakearealink2;
500 $instance->introformat = FORMAT_HTML;
501 $assign->update_instance($instance);
502 $params = array('modulename' => 'assign', 'instance' => $assign->get_instance()->id);
503 $event = $DB->get_record('event', $params);
504 $this->assertNotEmpty($event);
505 $this->assertSame('new', $event->description); // The pluginfile links are removed.
507 // Create an assignment with a description that should be hidden.
508 $assign = $this->create_instance(array('duedate'=>$now + 160,
509 'alwaysshowdescription'=>false,
510 'allowsubmissionsfromdate'=>$now + 60,
511 'intro'=>'Some text'));
513 // Get the event from the calendar.
514 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
515 $event = $DB->get_record('event', $params);
517 $this->assertEmpty($event->description);
519 // Change the allowsubmissionfromdate to the past - do this directly in the DB
520 // because if we call the assignment update method - it will update the calendar
521 // and we want to test that this works from cron.
522 $DB->set_field('assign', 'allowsubmissionsfromdate', $now - 60, array('id'=>$assign->get_instance()->id));
523 // Run cron to update the event in the calendar.
525 $event = $DB->get_record('event', $params);
527 $this->assertContains('Some text', $event->description);
531 public function test_update_instance() {
534 $this->setUser($this->editingteachers[0]);
535 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
538 $instance = $assign->get_instance();
539 $instance->duedate = $now;
540 $instance->instance = $instance->id;
541 $instance->assignsubmission_onlinetext_enabled = 1;
543 $assign->update_instance($instance);
545 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
546 $this->assertEquals($now, $instance->duedate);
549 public function test_cannot_submit_empty() {
552 $this->setUser($this->editingteachers[0]);
553 $assign = $this->create_instance(array('submissiondrafts'=>1));
555 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
557 // Test you cannot see the submit button for an offline assignment regardless.
558 $this->setUser($this->students[0]);
559 $output = $assign->view_student_summary($this->students[0], true);
560 $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Can submit empty offline assignment');
562 // Test you cannot see the submit button for an online text assignment with no submission.
563 $this->setUser($this->editingteachers[0]);
564 $instance = $assign->get_instance();
565 $instance->instance = $instance->id;
566 $instance->assignsubmission_onlinetext_enabled = 1;
568 $assign->update_instance($instance);
569 $this->setUser($this->students[0]);
570 $output = $assign->view_student_summary($this->students[0], true);
571 $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Cannot submit empty onlinetext assignment');
573 // Simulate a submission.
574 $submission = $assign->get_user_submission($this->students[0]->id, true);
575 $data = new stdClass();
576 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
577 'text'=>'Submission text',
578 'format'=>FORMAT_MOODLE);
579 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
580 $plugin->save($submission, $data);
581 // Test you can see the submit button for an online text assignment with a submission.
582 $output = $assign->view_student_summary($this->students[0], true);
583 $this->assertContains(get_string('submitassignment', 'assign'), $output, 'Can submit non empty onlinetext assignment');
586 public function test_list_participants() {
589 $this->create_extra_users();
590 $this->setUser($this->editingteachers[0]);
591 $assign = $this->create_instance(array('grade'=>100));
593 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
595 // Teacher with user preference set should see suspended users as well.
596 set_user_preference('grade_report_showonlyactiveenrol', false);
597 $assign = $this->create_instance(array('grade'=>100));
598 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT,
599 count($assign->list_participants(null, true)));
601 // Non-editing teacher should not see suspended users, even if user preference is set.
602 $this->setUser($this->teachers[0]);
603 set_user_preference('grade_report_showonlyactiveenrol', false);
604 $assign = $this->create_instance(array('grade'=>100));
605 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
607 // Turn on availability and a group restriction, and check that it doesn't
608 // show users who aren't in the group.
609 $CFG->enableavailability = true;
610 $specialgroup = $this->getDataGenerator()->create_group(
611 array('courseid' => $this->course->id));
612 $assign = $this->create_instance(array('grade' => 100,
613 'availability' => json_encode(\core_availability\tree::get_root_json(
614 array(\availability_group\condition::get_json($specialgroup->id))))));
615 groups_add_member($specialgroup, $this->students[0]);
616 groups_add_member($specialgroup, $this->students[1]);
617 $this->assertEquals(2, count($assign->list_participants(null, true)));
620 public function test_count_teams() {
621 $this->create_extra_users();
622 $this->setUser($this->editingteachers[0]);
623 $assign = $this->create_instance(array('teamsubmission'=>1));
625 $this->assertEquals(self::GROUP_COUNT + 1, $assign->count_teams());
628 public function test_submit_to_default_group() {
631 $this->preventResetByRollback();
632 $sink = $this->redirectMessages();
634 $this->setUser($this->editingteachers[0]);
635 $params = array('teamsubmission' => 1,
636 'assignsubmission_onlinetext_enabled' => 1,
637 'submissiondrafts'=>0);
638 $assign = $this->create_instance($params);
640 $newstudent = $this->getDataGenerator()->create_user();
641 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
642 $this->getDataGenerator()->enrol_user($newstudent->id,
645 $this->setUser($newstudent);
646 $data = new stdClass();
647 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
648 'text'=>'Submission text',
649 'format'=>FORMAT_MOODLE);
652 $group = $assign->get_submission_group($newstudent->id);
653 $this->assertFalse($group, 'New student is in default group');
654 $assign->save_submission($data, $notices);
655 $this->assertEmpty($notices, 'No errors on save submission');
660 public function test_count_submissions() {
661 $this->create_extra_users();
662 $this->setUser($this->editingteachers[0]);
663 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
665 // Simulate a submission.
666 $this->setUser($this->extrastudents[0]);
667 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
668 $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
669 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
670 // Leave this one as DRAFT.
671 $data = new stdClass();
672 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
673 'text'=>'Submission text',
674 'format'=>FORMAT_MOODLE);
675 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
676 $plugin->save($submission, $data);
678 // Simulate adding a grade.
679 $this->setUser($this->teachers[0]);
680 $data = new stdClass();
681 $data->grade = '50.0';
682 $assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0);
684 // Simulate a submission.
685 $this->setUser($this->extrastudents[1]);
686 $submission = $assign->get_user_submission($this->extrastudents[1]->id, true);
687 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
688 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
689 $data = new stdClass();
690 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
691 'text'=>'Submission text',
692 'format'=>FORMAT_MOODLE);
693 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
694 $plugin->save($submission, $data);
696 // Simulate a submission.
697 $this->setUser($this->extrastudents[2]);
698 $submission = $assign->get_user_submission($this->extrastudents[2]->id, true);
699 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
700 $assign->testable_update_submission($submission, $this->extrastudents[2]->id, true, false);
701 $data = new stdClass();
702 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
703 'text'=>'Submission text',
704 'format'=>FORMAT_MOODLE);
705 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
706 $plugin->save($submission, $data);
708 // Simulate a submission.
709 $this->setUser($this->extrastudents[3]);
710 $submission = $assign->get_user_submission($this->extrastudents[3]->id, true);
711 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
712 $assign->testable_update_submission($submission, $this->extrastudents[3]->id, true, false);
713 $data = new stdClass();
714 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
715 'text'=>'Submission text',
716 'format'=>FORMAT_MOODLE);
717 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
718 $plugin->save($submission, $data);
720 // Simulate a submission for suspended user, this will never be counted.
721 $this->setUser($this->extrastudents[3]);
722 $submission = $assign->get_user_submission($this->extrasuspendedstudents[0]->id, true);
723 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
724 $assign->testable_update_submission($submission, $this->extrasuspendedstudents[0]->id, true, false);
725 $data = new stdClass();
726 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
727 'text'=>'Submission text',
728 'format'=>FORMAT_MOODLE);
729 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
730 $plugin->save($submission, $data);
732 // Simulate adding a grade.
733 $this->setUser($this->teachers[0]);
734 $data = new stdClass();
735 $data->grade = '50.0';
736 $assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0);
737 $assign->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0);
739 $this->assertEquals(2, $assign->count_grades());
740 $this->assertEquals(4, $assign->count_submissions());
741 $this->assertEquals(2, $assign->count_submissions_need_grading());
742 $this->assertEquals(3, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
743 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
746 public function test_get_grading_userid_list() {
747 $this->create_extra_users();
748 $this->setUser($this->editingteachers[0]);
749 $assign = $this->create_instance();
751 $users = $assign->testable_get_grading_userid_list();
752 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($users));
754 $this->setUser($this->editingteachers[0]);
755 set_user_preference('grade_report_showonlyactiveenrol', false);
756 $assign = $this->create_instance();
758 $users = $assign->testable_get_grading_userid_list();
759 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT, count($users));
762 public function test_cron() {
763 // First run cron so there are no messages waiting to be sent (from other tests).
767 // Now create an assignment and add some feedback.
768 $this->setUser($this->editingteachers[0]);
769 $assign = $this->create_instance(array('sendstudentnotifications'=>1));
771 // Simulate adding a grade.
772 $this->setUser($this->teachers[0]);
773 $data = new stdClass();
774 $data->grade = '50.0';
775 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
776 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
778 $data->sendstudentnotifications = false;
779 $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0);
781 // Now run cron and see that one message was sent.
782 $this->preventResetByRollback();
783 $sink = $this->redirectMessages();
785 $this->expectOutputRegex('/Done processing 2 assignment submissions/');
788 $messages = $sink->get_messages();
789 // The sent count should be 2, because the 3rd one was marked as do not send notifications.
790 $this->assertEquals(2, count($messages));
791 $this->assertEquals(1, $messages[0]->notification);
792 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
795 public function test_is_graded() {
796 $this->setUser($this->editingteachers[0]);
797 $assign = $this->create_instance();
799 // Simulate adding a grade.
800 $this->setUser($this->teachers[0]);
801 $data = new stdClass();
802 $data->grade = '50.0';
803 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
805 $this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id));
806 $this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
809 public function test_can_grade() {
812 $this->setUser($this->editingteachers[0]);
813 $assign = $this->create_instance();
815 $this->setUser($this->students[0]);
816 $this->assertEquals(false, $assign->can_grade());
817 $this->setUser($this->editingteachers[0]);
818 $this->assertEquals(true, $assign->can_grade());
819 $this->setUser($this->teachers[0]);
820 $this->assertEquals(true, $assign->can_grade());
822 // Test the viewgrades capability - without mod/assign:grade.
823 $this->setUser($this->students[0]);
824 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
825 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
826 $this->assertEquals(false, $assign->can_grade());
829 public function test_can_view_submission() {
832 $this->create_extra_users();
833 $this->setUser($this->editingteachers[0]);
834 $assign = $this->create_instance();
836 $this->setUser($this->students[0]);
837 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
838 $this->assertEquals(false, $assign->can_view_submission($this->students[1]->id));
839 $this->assertEquals(false, $assign->can_view_submission($this->teachers[0]->id));
840 $this->setUser($this->teachers[0]);
841 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
842 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
843 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
844 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
845 $this->setUser($this->editingteachers[0]);
846 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
847 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
848 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
849 $this->assertEquals(true, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
851 // Test the viewgrades capability - without mod/assign:grade.
852 $this->setUser($this->students[0]);
853 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
854 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
855 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
856 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
857 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
858 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
862 public function test_update_submission() {
863 $this->create_extra_users();
864 $this->setUser($this->editingteachers[0]);
865 $assign = $this->create_instance();
867 $this->setUser($this->extrastudents[0]);
869 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
870 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
872 $this->setUser($this->teachers[0]);
873 // Verify the gradebook update.
874 $gradinginfo = grade_get_grades($this->course->id,
877 $assign->get_instance()->id,
878 $this->extrastudents[0]->id);
880 $this->assertEquals($this->extrastudents[0]->id,
881 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
883 // Now verify group assignments.
884 $this->setUser($this->editingteachers[0]);
885 $assign = $this->create_instance(array('teamsubmission'=>1));
887 $this->setUser($this->extrastudents[0]);
889 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
890 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
892 // Check that at least 2 active members and 1 suspended member of the submission group had their submission updated.
894 $this->setUser($this->editingteachers[0]);
895 $gradinginfo = grade_get_grades($this->course->id,
898 $assign->get_instance()->id,
899 $this->extrastudents[0]->id);
901 $this->assertEquals($this->extrastudents[0]->id,
902 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
904 $gradinginfo = grade_get_grades($this->course->id,
907 $assign->get_instance()->id,
908 $this->extrastudents[self::GROUP_COUNT]->id);
910 $this->assertEquals($this->extrastudents[self::GROUP_COUNT]->id,
911 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT]->id]->usermodified);
913 $gradinginfo = grade_get_grades($this->course->id,
916 $assign->get_instance()->id,
917 $this->extrasuspendedstudents[0]->id);
918 $this->assertEquals($this->extrasuspendedstudents[0]->id,
919 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[0]->id]->usermodified);
921 // Check the same with non-editing teacher and make sure submission is not updated for suspended user.
922 $this->setUser($this->editingteachers[0]);
923 $assign = $this->create_instance(array('teamsubmission'=>1));
925 $this->setUser($this->extrastudents[1]);
927 $submission = $assign->get_group_submission($this->extrastudents[1]->id, 0, true);
928 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, true);
930 $this->setUser($this->teachers[0]);
931 $gradinginfo = grade_get_grades($this->course->id,
934 $assign->get_instance()->id,
935 $this->extrastudents[1]->id);
937 $this->assertEquals($this->extrastudents[1]->id,
938 $gradinginfo->items[0]->grades[$this->extrastudents[1]->id]->usermodified);
940 $gradinginfo = grade_get_grades($this->course->id,
943 $assign->get_instance()->id,
944 $this->extrastudents[self::GROUP_COUNT+1]->id);
946 $this->assertEquals($this->extrastudents[self::GROUP_COUNT+1]->id,
947 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT+1]->id]->usermodified);
949 $gradinginfo = grade_get_grades($this->course->id,
952 $assign->get_instance()->id,
953 $this->extrasuspendedstudents[1]->id);
954 $this->assertEquals($this->extrasuspendedstudents[1]->id,
955 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[1]->id]->usermodified);
957 // Now verify blind marking.
958 $this->setUser($this->editingteachers[0]);
959 $assign = $this->create_instance(array('blindmarking'=>1));
961 $this->setUser($this->extrastudents[0]);
963 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
964 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
966 $this->setUser($this->editingteachers[0]);
967 $gradinginfo = grade_get_grades($this->course->id,
970 $assign->get_instance()->id,
971 $this->extrastudents[0]->id);
973 $this->assertEquals(null, $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->datesubmitted);
976 public function test_group_submissions_submit_for_marking_requireallteammemberssubmit() {
979 $this->create_extra_users();
980 // Now verify group assignments.
981 $this->setUser($this->editingteachers[0]);
982 $assign = $this->create_instance(array('teamsubmission'=>1,
983 'assignsubmission_onlinetext_enabled'=>1,
984 'submissiondrafts'=>1,
985 'requireallteammemberssubmit'=>1));
986 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
989 $this->setUser($this->extrastudents[0]);
990 $data = new stdClass();
991 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
992 'text'=>'Submission text',
993 'format'=>FORMAT_MOODLE);
996 $assign->save_submission($data, $notices);
998 // Check we can see the submit button.
999 $output = $assign->view_student_summary($this->extrastudents[0], true);
1000 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1002 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1003 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1004 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
1006 // Check that the student does not see "Submit" button.
1007 $output = $assign->view_student_summary($this->extrastudents[0], true);
1008 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1010 // Change to another user in the same group.
1011 $this->setUser($this->extrastudents[self::GROUP_COUNT]);
1012 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1013 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1015 $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
1016 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1017 $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
1018 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1019 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1022 public function test_group_submissions_submit_for_marking() {
1025 $this->create_extra_users();
1026 // Now verify group assignments.
1027 $this->setUser($this->editingteachers[0]);
1028 $assign = $this->create_instance(array('teamsubmission'=>1,
1029 'assignsubmission_onlinetext_enabled'=>1,
1030 'submissiondrafts'=>1,
1031 'requireallteammemberssubmit'=>0,
1032 'duedate' => time() - 2*24*60*60));
1033 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1035 $this->setUser($this->extrastudents[0]);
1036 // Add a submission.
1037 $data = new stdClass();
1038 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1039 'text'=>'Submission text',
1040 'format'=>FORMAT_MOODLE);
1043 $assign->save_submission($data, $notices);
1045 // Check we can see the submit button.
1046 $output = $assign->view_student_summary($this->extrastudents[0], true);
1047 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1048 $this->assertContains(get_string('timeremaining', 'assign'), $output);
1049 $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60)), $output);
1051 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1052 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1053 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
1055 // Check that the student does not see "Submit" button.
1056 $output = $assign->view_student_summary($this->extrastudents[0], true);
1057 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1059 // Change to another user in the same group.
1060 $this->setUser($this->extrastudents[self::GROUP_COUNT]);
1061 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1062 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1064 // Check that time remaining is not overdue.
1065 $this->assertContains(get_string('timeremaining', 'assign'), $output);
1066 $this->assertContains(get_string('submittedlate', 'assign', format_time(2*24*60*60)), $output);
1068 $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
1069 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1070 $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
1071 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1072 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1075 public function test_submissions_open() {
1076 $this->setUser($this->editingteachers[0]);
1079 $tomorrow = $now + 24*60*60;
1080 $oneweek = $now + 7*24*60*60;
1081 $yesterday = $now - 24*60*60;
1083 $assign = $this->create_instance();
1084 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1086 $assign = $this->create_instance(array('duedate'=>$tomorrow));
1087 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1089 $assign = $this->create_instance(array('duedate'=>$yesterday));
1090 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1092 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$tomorrow));
1093 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1095 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$yesterday));
1096 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
1098 $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
1099 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1101 $assign = $this->create_instance(array('submissiondrafts'=>1));
1102 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1104 $this->setUser($this->students[0]);
1106 $submission = $assign->get_user_submission($this->students[0]->id, true);
1107 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1108 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1109 $this->setUser($this->editingteachers[0]);
1110 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
1113 public function test_get_graders() {
1114 $this->create_extra_users();
1115 $this->setUser($this->editingteachers[0]);
1117 // Create an assignment with no groups.
1118 $assign = $this->create_instance();
1119 $this->assertCount(self::DEFAULT_TEACHER_COUNT +
1120 self::DEFAULT_EDITING_TEACHER_COUNT +
1121 self::EXTRA_TEACHER_COUNT +
1122 self::EXTRA_EDITING_TEACHER_COUNT,
1123 $assign->testable_get_graders($this->students[0]->id));
1125 // Force create an assignment with SEPARATEGROUPS.
1126 $data = new stdClass();
1127 $data->courseid = $this->course->id;
1128 $data->name = 'Grouping';
1129 $groupingid = groups_create_grouping($data);
1130 groups_assign_grouping($groupingid, $this->groups[0]->id);
1131 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
1133 $this->setUser($this->students[1]);
1134 $this->assertCount(4, $assign->testable_get_graders($this->students[0]->id));
1135 // Note the second student is in a group that is not in the grouping.
1136 // This means that we get all graders that are not in a group in the grouping.
1137 $this->assertCount(10, $assign->testable_get_graders($this->students[1]->id));
1140 public function test_get_notified_users() {
1143 $capability = 'mod/assign:receivegradernotifications';
1144 $coursecontext = context_course::instance($this->course->id);
1145 $role = $DB->get_record('role', array('shortname' => 'teacher'));
1147 $this->create_extra_users();
1148 $this->setUser($this->editingteachers[0]);
1150 // Create an assignment with no groups.
1151 $assign = $this->create_instance();
1153 $this->assertCount(self::DEFAULT_TEACHER_COUNT +
1154 self::DEFAULT_EDITING_TEACHER_COUNT +
1155 self::EXTRA_TEACHER_COUNT +
1156 self::EXTRA_EDITING_TEACHER_COUNT,
1157 $assign->testable_get_notifiable_users($this->students[0]->id));
1159 // Change nonediting teachers role to not receive grader notifications.
1160 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
1162 $this->assertCount(self::DEFAULT_EDITING_TEACHER_COUNT +
1163 self::EXTRA_EDITING_TEACHER_COUNT,
1164 $assign->testable_get_notifiable_users($this->students[0]->id));
1166 // Reset nonediting teachers role to default.
1167 unassign_capability($capability, $role->id, $coursecontext);
1169 // Force create an assignment with SEPARATEGROUPS.
1170 $data = new stdClass();
1171 $data->courseid = $this->course->id;
1172 $data->name = 'Grouping';
1173 $groupingid = groups_create_grouping($data);
1174 groups_assign_grouping($groupingid, $this->groups[0]->id);
1175 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
1177 $this->setUser($this->students[1]);
1178 $this->assertCount(4, $assign->testable_get_notifiable_users($this->students[0]->id));
1179 // Note the second student is in a group that is not in the grouping.
1180 // This means that we get all graders that are not in a group in the grouping.
1181 $this->assertCount(10, $assign->testable_get_notifiable_users($this->students[1]->id));
1183 // Change nonediting teachers role to not receive grader notifications.
1184 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
1186 $this->assertCount(2, $assign->testable_get_notifiable_users($this->students[0]->id));
1187 // Note the second student is in a group that is not in the grouping.
1188 // This means that we get all graders that are not in a group in the grouping.
1189 $this->assertCount(5, $assign->testable_get_notifiable_users($this->students[1]->id));
1192 public function test_group_members_only() {
1195 $this->setAdminUser();
1196 $this->create_extra_users();
1197 $CFG->enableavailability = true;
1198 $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id));
1199 groups_assign_grouping($grouping->id, $this->groups[0]->id);
1201 // Force create an assignment with SEPARATEGROUPS.
1202 $instance = $this->getDataGenerator()->create_module('assign', array('course'=>$this->course->id),
1203 array('availability' => json_encode(\core_availability\tree::get_root_json(array(
1204 \availability_grouping\condition::get_json()))),
1205 'groupingid' => $grouping->id));
1207 $cm = get_coursemodule_from_instance('assign', $instance->id);
1208 $context = context_module::instance($cm->id);
1209 $assign = new testable_assign($context, $cm, $this->course);
1211 $this->setUser($this->teachers[0]);
1212 get_fast_modinfo($this->course, 0, true);
1213 $this->assertCount(5, $assign->list_participants(0, true));
1217 public function test_get_uniqueid_for_user() {
1218 $this->setUser($this->editingteachers[0]);
1219 $assign = $this->create_instance();
1221 foreach ($this->students as $student) {
1222 $uniqueid = $assign->get_uniqueid_for_user($student->id);
1223 $this->assertEquals($student->id, $assign->get_user_id_for_uniqueid($uniqueid));
1227 public function test_show_student_summary() {
1230 $this->setUser($this->editingteachers[0]);
1231 $assign = $this->create_instance();
1232 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1234 // No feedback should be available because this student has not been graded.
1235 $this->setUser($this->students[0]);
1236 $output = $assign->view_student_summary($this->students[0], true);
1237 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if there is no grade');
1238 // Simulate adding a grade.
1239 $this->setUser($this->teachers[0]);
1240 $data = new stdClass();
1241 $data->grade = '50.0';
1242 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1244 // Now we should see the feedback.
1245 $this->setUser($this->students[0]);
1246 $output = $assign->view_student_summary($this->students[0], true);
1247 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback if there is a grade');
1249 // Now hide the grade in gradebook.
1250 $this->setUser($this->teachers[0]);
1251 require_once($CFG->libdir.'/gradelib.php');
1252 $gradeitem = new grade_item(array(
1253 'itemtype' => 'mod',
1254 'itemmodule' => 'assign',
1255 'iteminstance' => $assign->get_instance()->id,
1256 'courseid' => $this->course->id));
1258 $gradeitem->set_hidden(1, false);
1260 // No feedback should be available because the grade is hidden.
1261 $this->setUser($this->students[0]);
1262 $output = $assign->view_student_summary($this->students[0], true);
1263 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
1265 // Do the same but add feedback.
1266 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
1268 $this->setUser($this->teachers[0]);
1269 $grade = $assign->get_user_grade($this->students[0]->id, true);
1270 $data = new stdClass();
1271 $data->assignfeedbackcomments_editor = array('text'=>'Tomato sauce',
1272 'format'=>FORMAT_MOODLE);
1273 $plugin = $assign->get_feedback_plugin_by_type('comments');
1274 $plugin->save($grade, $data);
1276 // Should have feedback but no grade.
1277 $this->setUser($this->students[0]);
1278 $output = $assign->view_student_summary($this->students[0], true);
1279 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback even if there is no grade');
1280 $this->assertEquals(false, strpos($output, 'Grade'), 'Do not show grade when there is no grade.');
1281 $this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.');
1283 // Now hide the grade in gradebook.
1284 $this->setUser($this->teachers[0]);
1285 $gradeitem = new grade_item(array(
1286 'itemtype' => 'mod',
1287 'itemmodule' => 'assign',
1288 'iteminstance' => $assign->get_instance()->id,
1289 'courseid' => $this->course->id));
1291 $gradeitem->set_hidden(1, false);
1293 // No feedback should be available because the grade is hidden.
1294 $this->setUser($this->students[0]);
1295 $output = $assign->view_student_summary($this->students[0], true);
1296 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
1299 public function test_attempt_reopen_method_manual() {
1302 $this->setUser($this->editingteachers[0]);
1303 $assign = $this->create_instance(array('attemptreopenmethod'=>ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
1305 'submissiondrafts'=>1,
1306 'assignsubmission_onlinetext_enabled'=>1));
1307 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1309 // Student should be able to see an add submission button.
1310 $this->setUser($this->students[0]);
1311 $output = $assign->view_student_summary($this->students[0], true);
1312 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1314 // Add a submission.
1316 $submission = $assign->get_user_submission($this->students[0]->id, true);
1317 $data = new stdClass();
1318 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1319 'text'=>'Submission text',
1320 'format'=>FORMAT_MOODLE);
1321 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1322 $plugin->save($submission, $data);
1324 // And now submit it for marking.
1325 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1326 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1328 // Verify the student cannot make changes to the submission.
1329 $output = $assign->view_student_summary($this->students[0], true);
1330 $this->assertEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1332 // Mark the submission.
1333 $this->setUser($this->teachers[0]);
1334 $data = new stdClass();
1335 $data->grade = '50.0';
1336 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1338 // Check the student can see the grade.
1339 $this->setUser($this->students[0]);
1340 $output = $assign->view_student_summary($this->students[0], true);
1341 $this->assertNotEquals(false, strpos($output, '50.0'));
1343 // Allow the student another attempt.
1344 $this->teachers[0]->ignoresesskey = true;
1345 $this->setUser($this->teachers[0]);
1346 $result = $assign->testable_process_add_attempt($this->students[0]->id);
1347 $this->assertEquals(true, $result);
1349 // Check that the previous attempt is now in the submission history table.
1350 $this->setUser($this->students[0]);
1351 $output = $assign->view_student_summary($this->students[0], true);
1352 // Need a better check.
1353 $this->assertNotEquals(false, strpos($output, 'Submission text'), 'Contains: Submission text');
1355 // Check that the student now has a button for Add a new attempt".
1356 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1357 // Check that the student now does not have a button for Submit.
1358 $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign')));
1360 // Check that the student now has a submission history.
1361 $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign')));
1363 $this->setUser($this->teachers[0]);
1364 // Check that the grading table loads correctly and contains this user.
1365 // This is also testing that we do not get duplicate rows in the grading table.
1366 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1367 $output = $assign->get_renderer()->render($gradingtable);
1368 $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
1370 // Should be 1 not 2.
1371 $this->assertEquals(1, $assign->count_submissions());
1372 $this->assertEquals(1, $assign->count_submissions_with_status('reopened'));
1373 $this->assertEquals(0, $assign->count_submissions_need_grading());
1374 $this->assertEquals(1, $assign->count_grades());
1376 // Change max attempts to unlimited.
1377 $formdata = clone($assign->get_instance());
1378 $formdata->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
1379 $formdata->instance = $formdata->id;
1380 $assign->update_instance($formdata);
1382 // Mark the submission again.
1383 $data = new stdClass();
1384 $data->grade = '60.0';
1385 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1);
1387 // Check the grade exists.
1388 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1389 $this->assertEquals(60, (int)$grades[$this->students[0]->id]->rawgrade);
1391 // Check we can reopen still.
1392 $result = $assign->testable_process_add_attempt($this->students[0]->id);
1393 $this->assertEquals(true, $result);
1395 // Should no longer have a grade because there is no grade for the latest attempt.
1396 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1397 $this->assertEmpty($grades);
1401 public function test_markingworkflow() {
1404 $this->setUser($this->editingteachers[0]);
1405 $assign = $this->create_instance(array('markingworkflow'=>1));
1406 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1408 // Mark the submission and set to notmarked.
1409 $this->setUser($this->teachers[0]);
1410 $data = new stdClass();
1411 $data->grade = '50.0';
1412 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED;
1413 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1415 // Check the student can't see the grade.
1416 $this->setUser($this->students[0]);
1417 $output = $assign->view_student_summary($this->students[0], true);
1418 $this->assertEquals(false, strpos($output, '50.0'));
1420 // Mark the submission and set to inmarking.
1421 $this->setUser($this->teachers[0]);
1422 $data = new stdClass();
1423 $data->grade = '50.0';
1424 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INMARKING;
1425 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1427 // Check the student can't see the grade.
1428 $this->setUser($this->students[0]);
1429 $output = $assign->view_student_summary($this->students[0], true);
1430 $this->assertEquals(false, strpos($output, '50.0'));
1432 // Mark the submission and set to readyforreview.
1433 $this->setUser($this->teachers[0]);
1434 $data = new stdClass();
1435 $data->grade = '50.0';
1436 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW;
1437 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1439 // Check the student can't see the grade.
1440 $this->setUser($this->students[0]);
1441 $output = $assign->view_student_summary($this->students[0], true);
1442 $this->assertEquals(false, strpos($output, '50.0'));
1444 // Mark the submission and set to inreview.
1445 $this->setUser($this->teachers[0]);
1446 $data = new stdClass();
1447 $data->grade = '50.0';
1448 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW;
1449 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1451 // Check the student can't see the grade.
1452 $this->setUser($this->students[0]);
1453 $output = $assign->view_student_summary($this->students[0], true);
1454 $this->assertEquals(false, strpos($output, '50.0'));
1456 // Mark the submission and set to readyforrelease.
1457 $this->setUser($this->teachers[0]);
1458 $data = new stdClass();
1459 $data->grade = '50.0';
1460 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE;
1461 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1463 // Check the student can't see the grade.
1464 $this->setUser($this->students[0]);
1465 $output = $assign->view_student_summary($this->students[0], true);
1466 $this->assertEquals(false, strpos($output, '50.0'));
1468 // Mark the submission and set to released.
1469 $this->setUser($this->teachers[0]);
1470 $data = new stdClass();
1471 $data->grade = '50.0';
1472 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED;
1473 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1475 // Check the student can see the grade.
1476 $this->setUser($this->students[0]);
1477 $output = $assign->view_student_summary($this->students[0], true);
1478 $this->assertNotEquals(false, strpos($output, '50.0'));
1481 public function test_markerallocation() {
1484 $this->setUser($this->editingteachers[0]);
1485 $assign = $this->create_instance(array('markingworkflow'=>1, 'markingallocation'=>1));
1486 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1488 // Allocate marker to submission.
1489 $data = new stdClass();
1490 $data->allocatedmarker = $this->teachers[0]->id;
1491 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1493 // Check the allocated marker can view the submission.
1494 $this->setUser($this->teachers[0]);
1495 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1496 $output = $assign->get_renderer()->render($gradingtable);
1497 $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
1499 // Check that other teachers can't view this submission.
1500 $this->setUser($this->teachers[1]);
1501 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1502 $output = $assign->get_renderer()->render($gradingtable);
1503 $this->assertNotEquals(true, strpos($output, $this->students[0]->lastname));
1508 public function test_teacher_submit_for_student() {
1511 $this->preventResetByRollback();
1512 $sink = $this->redirectMessages();
1514 $this->setUser($this->editingteachers[0]);
1516 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1));
1517 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1519 $this->setUser($this->students[0]);
1520 // Simulate a submission.
1521 $data = new stdClass();
1522 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1523 'text'=>'Student submission text',
1524 'format'=>FORMAT_MOODLE);
1527 $assign->save_submission($data, $notices);
1529 // Check that the submission text was saved.
1530 $output = $assign->view_student_summary($this->students[0], true);
1531 $this->assertContains('Student submission text', $output, 'Contains student submission text');
1533 // Check that a teacher teacher with the extra capability can edit a students submission.
1534 $this->setUser($this->teachers[0]);
1535 $data = new stdClass();
1536 $data->userid = $this->students[0]->id;
1537 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1538 'text'=>'Teacher edited submission text',
1539 'format'=>FORMAT_MOODLE);
1541 // Add the required capability.
1542 $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
1543 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
1544 role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id);
1545 accesslib_clear_all_caches_for_unit_testing();
1547 // Try to save the submission.
1549 $assign->save_submission($data, $notices);
1551 // Check that the teacher can submit the students work.
1552 $data = new stdClass();
1553 $data->userid = $this->students[0]->id;
1555 $assign->submit_for_grading($data, $notices);
1557 // Revert to draft so the student can edit it.
1558 $assign->revert_to_draft($this->students[0]->id);
1560 $this->setUser($this->students[0]);
1562 // Check that the submission text was saved.
1563 $output = $assign->view_student_summary($this->students[0], true);
1564 $this->assertContains('Teacher edited submission text', $output, 'Contains student submission text');
1566 // Check that the student can submit their work.
1567 $data = new stdClass();
1568 $assign->submit_for_grading($data, $notices);
1570 $output = $assign->view_student_summary($this->students[0], true);
1571 $this->assertNotContains(get_string('addsubmission', 'assign'), $output);
1573 // Set to a default editing teacher who should not be able to edit this submission.
1574 $this->setUser($this->editingteachers[1]);
1576 // Revert to draft so the submission is editable.
1577 $assign->revert_to_draft($this->students[0]->id);
1579 $data = new stdClass();
1580 $data->userid = $this->students[0]->id;
1581 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1582 'text'=>'Teacher 2 edited submission text',
1583 'format'=>FORMAT_MOODLE);
1586 $this->setExpectedException('moodle_exception');
1587 $assign->save_submission($data, $notices);
1592 public function test_disable_submit_after_cutoff_date() {
1595 $this->setUser($this->editingteachers[0]);
1597 $tomorrow = $now + 24*60*60;
1598 $lastweek = $now - 7*24*60*60;
1599 $yesterday = $now - 24*60*60;
1601 $assign = $this->create_instance(array('duedate'=>$yesterday,
1602 'cutoffdate'=>$tomorrow,
1603 'assignsubmission_onlinetext_enabled'=>1));
1604 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1606 // Student should be able to see an add submission button.
1607 $this->setUser($this->students[0]);
1608 $output = $assign->view_student_summary($this->students[0], true);
1609 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1611 // Add a submission but don't submit now.
1612 $submission = $assign->get_user_submission($this->students[0]->id, true);
1613 $data = new stdClass();
1614 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1615 'text'=>'Submission text',
1616 'format'=>FORMAT_MOODLE);
1617 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1618 $plugin->save($submission, $data);
1620 // Create another instance with cut-off and due-date already passed.
1621 $this->setUser($this->editingteachers[0]);
1623 $assign = $this->create_instance(array('duedate'=>$lastweek,
1624 'cutoffdate'=>$yesterday,
1625 'assignsubmission_onlinetext_enabled'=>1));
1627 $this->setUser($this->students[0]);
1628 $output = $assign->view_student_summary($this->students[0], true);
1629 $this->assertNotContains($output, get_string('editsubmission', 'assign'),
1630 'Should not be able to edit after cutoff date.');
1631 $this->assertNotContains($output, get_string('submitassignment', 'assign'),
1632 'Should not be able to submit after cutoff date.');
1635 * Testing for submission comment plugin settings
1637 public function test_submission_comment_plugin_settings() {
1640 $commentconfig = false;
1641 if (!empty($CFG->usecomments)) {
1642 $commentconfig = $CFG->usecomments;
1645 $CFG->usecomments = true;
1646 $assign = $this->create_instance();
1647 $plugin = $assign->get_submission_plugin_by_type('comments');
1648 $this->assertEquals(1, $plugin->is_enabled('enabled'));
1650 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0));
1651 $plugin = $assign->get_submission_plugin_by_type('comments');
1652 $this->assertEquals(1, $plugin->is_enabled('enabled'));
1654 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1));
1655 $plugin = $assign->get_submission_plugin_by_type('comments');
1656 $this->assertEquals(1, $plugin->is_enabled('enabled'));
1658 $CFG->usecomments = false;
1659 $assign = $this->create_instance();
1660 $plugin = $assign->get_submission_plugin_by_type('comments');
1661 $this->assertEquals(0, $plugin->is_enabled('enabled'));
1663 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0));
1664 $plugin = $assign->get_submission_plugin_by_type('comments');
1665 $this->assertEquals(0, $plugin->is_enabled('enabled'));
1667 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1));
1668 $plugin = $assign->get_submission_plugin_by_type('comments');
1669 $this->assertEquals(0, $plugin->is_enabled('enabled'));
1671 $CFG->usecomments = $commentconfig;
1675 * Testing for comment inline settings
1677 public function test_feedback_comment_commentinline() {
1680 $sourcetext = "Hello!
1682 I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness.
1684 URL outside a tag: https://moodle.org/logo/logo-240x60.gif
1685 Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif
1687 External link 1:<img src='https://moodle.org/logo/logo-240x60.gif' alt='Moodle'/>
1688 External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\"/>
1689 Internal link 1:<img src='@@PLUGINFILE@@/logo-240x60.gif' alt='Moodle'/>
1690 Internal link 2:<img alt=\"Moodle\" src=\"@@PLUGINFILE@@logo-240x60.gif\"/>
1691 Anchor link 1:<a href=\"@@PLUGINFILE@@logo-240x60.gif\" alt=\"bananas\">Link text</a>
1692 Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
1695 // Note the internal images have been stripped and the html is purified (quotes fixed in this case).
1696 $filteredtext = "Hello!
1698 I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness.
1700 URL outside a tag: https://moodle.org/logo/logo-240x60.gif
1701 Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif
1703 External link 1:<img src=\"https://moodle.org/logo/logo-240x60.gif\" alt=\"Moodle\" />
1704 External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\" />
1707 Anchor link 1:Link text
1708 Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
1711 $this->setUser($this->editingteachers[0]);
1712 $params = array('assignsubmission_onlinetext_enabled' => 1,
1713 'assignfeedback_comments_enabled' => 1,
1714 'assignfeedback_comments_commentinline' => 1);
1715 $assign = $this->create_instance($params);
1717 $this->setUser($this->students[0]);
1718 // Add a submission but don't submit now.
1719 $submission = $assign->get_user_submission($this->students[0]->id, true);
1720 $data = new stdClass();
1722 // Test the internal link is stripped, but the external one is not.
1723 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1724 'text'=>$sourcetext,
1725 'format'=>FORMAT_MOODLE);
1727 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1728 $plugin->save($submission, $data);
1730 $this->setUser($this->editingteachers[0]);
1732 $data = new stdClass();
1733 require_once($CFG->dirroot . '/mod/assign/gradeform.php');
1734 $pagination = array('userid'=>$this->students[0]->id,
1737 'useridlistid'=>time(),
1738 'attemptnumber'=>0);
1739 $formparams = array($assign, $data, $pagination);
1740 $mform = new mod_assign_grade_form(null, $formparams);
1742 $this->assertEquals($filteredtext, $data->assignfeedbackcomments_editor['text']);
1746 * Testing for feedback comment plugin settings
1748 public function test_feedback_plugin_settings() {
1750 $assign = $this->create_instance();
1751 $plugin = $assign->get_feedback_plugin_by_type('comments');
1752 $this->assertEquals(0, $plugin->is_enabled('enabled'));
1754 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 0));
1755 $plugin = $assign->get_feedback_plugin_by_type('comments');
1756 $this->assertEquals(0, $plugin->is_enabled('enabled'));
1758 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
1759 $plugin = $assign->get_feedback_plugin_by_type('comments');
1760 $this->assertEquals(1, $plugin->is_enabled('enabled'));
1764 * Testing if gradebook feedback plugin is enabled.
1766 public function test_is_gradebook_feedback_enabled() {
1767 $adminconfig = get_config('assign');
1768 $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;
1770 // Create assignment with gradebook feedback enabled and grade = 0.
1771 $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 1, 'grades' => 0));
1773 // Get gradebook feedback plugin.
1774 $gradebookplugintype = str_replace('assignfeedback_', '', $gradebookplugin);
1775 $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype);
1776 $this->assertEquals(1, $plugin->is_enabled('enabled'));
1777 $this->assertEquals(1, $assign->is_gradebook_feedback_enabled());
1779 // Create assignment with gradebook feedback disabled and grade = 0.
1780 $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 0, 'grades' => 0));
1781 $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype);
1782 $this->assertEquals(0, $plugin->is_enabled('enabled'));
1786 * Testing can_edit_submission
1788 public function test_can_edit_submission() {
1790 $this->create_extra_users();
1792 $this->setAdminUser();
1793 // Create assignment (onlinetext).
1794 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1));
1795 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1797 // Check student can edit their own submission.
1798 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->students[0]->id));
1799 // Check student cannot edit others submission.
1800 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->students[1]->id));
1802 // Check teacher cannot (by default) edit a students submission.
1803 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id));
1805 // Add the required capability to edit a student submission.
1806 $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
1807 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
1808 role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id);
1809 accesslib_clear_all_caches_for_unit_testing();
1810 // Retest - should now have access.
1811 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id));
1813 // Force create an assignment with SEPARATEGROUPS.
1814 $data = new stdClass();
1815 $data->courseid = $this->course->id;
1816 $data->name = 'Grouping';
1817 $groupingid = groups_create_grouping($data);
1818 groups_assign_grouping($groupingid, $this->groups[0]->id);
1819 groups_assign_grouping($groupingid, $this->groups[1]->id);
1820 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
1822 // Add the capability to the new assignment for extra students 0 and 1.
1823 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
1824 role_assign($roleid, $this->extrastudents[0]->id, $assign->get_context()->id);
1825 role_assign($roleid, $this->extrastudents[1]->id, $assign->get_context()->id);
1826 accesslib_clear_all_caches_for_unit_testing();
1828 // Verify the extra student does not have the capability to edit a submission not in their group.
1829 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[1]->id));
1830 // Verify the extra student does have the capability to edit a submission in their group.
1831 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[0]->id));
1836 * Test if the view blind details capability works
1838 public function test_can_view_blind_details() {
1840 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1841 $managerrole = $DB->get_record('role', array('shortname' => 'manager'));
1843 $student = $this->students[0];// Get a student user.
1844 // Create a teacher. Shouldn't be able to view blind marking ID.
1845 $teacher = $this->getDataGenerator()->create_user();
1847 $this->getDataGenerator()->enrol_user($teacher->id,
1851 // Create a manager.. Should be able to view blind marking ID.
1852 $manager = $this->getDataGenerator()->create_user();
1853 $this->getDataGenerator()->enrol_user($manager->id,
1857 // Generate blind marking assignment.
1858 $assign = $this->create_instance(array('blindmarking' => 1));
1859 $this->assertEquals(true, $assign->is_blind_marking());
1861 // Test student names are hidden to teacher.
1862 $this->setUser($teacher);
1863 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
1864 $output = $assign->get_renderer()->render($gradingtable);
1865 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign'))); // "Participant" is somewhere on the page.
1866 $this->assertEquals(false, strpos($output, fullname($student))); // Students full name doesn't appear.
1868 // Test student names are visible to manager.
1869 $this->setUser($manager);
1870 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
1871 $output = $assign->get_renderer()->render($gradingtable);
1872 $this->assertEquals(false, strpos($output, get_string('hiddenuser', 'assign')));
1873 $this->assertEquals(true, strpos($output, fullname($student))); //students full name doesn't appear.