weekly release 2.9dev
[moodle.git] / mod / assign / tests / locallib_test.php
CommitLineData
47f48152
DW
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
27defined('MOODLE_INTERNAL') || die();
28
29global $CFG;
30require_once($CFG->dirroot . '/mod/assign/locallib.php');
31require_once($CFG->dirroot . '/mod/assign/upgradelib.php');
9c986ee0 32require_once($CFG->dirroot . '/mod/assign/tests/base_test.php');
47f48152
DW
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 */
9c986ee0 40class mod_assign_locallib_testcase extends mod_assign_base_testcase {
47f48152
DW
41
42 public function test_return_links() {
c2114099 43 global $PAGE;
47f48152
DW
44 $this->setUser($this->editingteachers[0]);
45 $returnaction = 'RETURNACTION';
c2114099 46 $returnparams = array('param'=>'1');
47f48152 47 $assign = $this->create_instance();
c2114099 48 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
47f48152
DW
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();
bd3b3bba 57 $installedplugins = array_keys(core_component::get_plugin_list('assignfeedback'));
11527706
DW
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 }
47f48152
DW
62 }
63
64 public function test_get_submission_plugins() {
65 $this->setUser($this->editingteachers[0]);
66 $assign = $this->create_instance();
bd3b3bba 67 $installedplugins = array_keys(core_component::get_plugin_list('assignsubmission'));
11527706
DW
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 }
47f48152
DW
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;
05a6445a 86 $this->students[0]->ignoresesskey = true;
47f48152
DW
87 $this->setUser($this->students[0]);
88 $this->setExpectedException('required_capability_exception');
05a6445a
DW
89 $assign->reveal_identities();
90 $this->students[0]->ignoresesskey = false;
47f48152
DW
91
92 // Test teachers cannot reveal identities.
93 $nopermission = false;
05a6445a 94 $this->teachers[0]->ignoresesskey = true;
47f48152
DW
95 $this->setUser($this->teachers[0]);
96 $this->setExpectedException('required_capability_exception');
05a6445a
DW
97 $assign->reveal_identities();
98 $this->teachers[0]->ignoresesskey = false;
47f48152
DW
99
100 // Test sesskey is required.
47f48152
DW
101 $this->setUser($this->editingteachers[0]);
102 $this->setExpectedException('moodle_exception');
05a6445a 103 $assign->reveal_identities();
47f48152
DW
104
105 // Test editingteacher can reveal identities if sesskey is ignored.
106 $this->editingteachers[0]->ignoresesskey = true;
107 $this->setUser($this->editingteachers[0]);
05a6445a 108 $assign->reveal_identities();
47f48152 109 $this->assertEquals(false, $assign->is_blind_marking());
05a6445a 110 $this->editingteachers[0]->ignoresesskey = false;
47f48152
DW
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
79397b56
DB
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.
5b460d65
MG
146 $extendedtime = time() + 2 * 24 * 60 * 60;
147 $assign->testable_save_user_extension($this->students[0]->id, $extendedtime);
79397b56
DB
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);
5b460d65 151 $this->assertContains(get_string('userextensiondate', 'assign', userdate($extendedtime)), $output);
79397b56
DB
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);
5b460d65 170 $this->assertContains(get_string('userextensiondate', 'assign', userdate($extendedtime)), $output);
79397b56
DB
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]);
a0f8db77 182 $time = time();
79397b56
DB
183 $assign = $this->create_instance(array(
184 'assignsubmission_onlinetext_enabled'=>1,
a0f8db77 185 'duedate' => $time - 4 * 24 * 60 * 60,
79397b56
DB
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);
a0f8db77
DW
196 $difftime = time() - $time;
197 $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60 + $difftime)), $output);
79397b56
DB
198
199 // Grant an extension that is in the past.
a0f8db77 200 $assign->testable_save_user_extension($this->students[0]->id, $time - 2 * 24 * 60 * 60);
79397b56
DB
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);
a0f8db77
DW
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);
79397b56
DB
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);
a0f8db77 219 $submittedtime = time();
79397b56
DB
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);
a0f8db77
DW
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);
79397b56
DB
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
47f48152
DW
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);
ab14ab74
FM
325
326 // The submission is still new.
327 $this->assertEquals(false, $assign->has_submissions_or_grades());
328
329 // Submit the submission.
330 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
331 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
47f48152
DW
332 $data = new stdClass();
333 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
334 'text'=>'Submission text',
335 'format'=>FORMAT_MOODLE);
336 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
337 $plugin->save($submission, $data);
338
339 // Now test again.
340 $this->assertEquals(true, $assign->has_submissions_or_grades());
341 // Set this back to default.
342 $this->students[0]->ignoresesskey = false;
343 }
344
345 public function test_delete_grades() {
346 $this->setUser($this->editingteachers[0]);
347 $assign = $this->create_instance();
348
349 // Simulate adding a grade.
350 $this->setUser($this->teachers[0]);
351 $data = new stdClass();
352 $data->grade = '50.0';
df211804 353 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
354
355 // Now see if the data is in the gradebook.
356 $gradinginfo = grade_get_grades($this->course->id,
357 'mod',
358 'assign',
359 $assign->get_instance()->id);
360
361 $this->assertNotEquals(0, count($gradinginfo->items));
362
363 $assign->testable_delete_grades();
364 $gradinginfo = grade_get_grades($this->course->id,
365 'mod',
366 'assign',
367 $assign->get_instance()->id);
368
369 $this->assertEquals(0, count($gradinginfo->items));
370 }
371
372 public function test_delete_instance() {
373 $this->setUser($this->editingteachers[0]);
374 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
375
376 // Simulate adding a grade.
377 $this->setUser($this->teachers[0]);
378 $data = new stdClass();
379 $data->grade = '50.0';
df211804 380 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
381
382 // Simulate a submission.
383 $this->setUser($this->students[0]);
384 $submission = $assign->get_user_submission($this->students[0]->id, true);
385 $data = new stdClass();
386 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
387 'text'=>'Submission text',
388 'format'=>FORMAT_MOODLE);
389 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
390 $plugin->save($submission, $data);
391
392 // Now try and delete.
393 $this->assertEquals(true, $assign->delete_instance());
394 }
395
396 public function test_reset_userdata() {
397 global $DB;
398
399 $now = time();
400 $this->setUser($this->editingteachers[0]);
401 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1,
402 'duedate'=>$now));
403
404 // Simulate adding a grade.
405 $this->setUser($this->teachers[0]);
406 $data = new stdClass();
407 $data->grade = '50.0';
df211804 408 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
409
410 // Simulate a submission.
411 $this->setUser($this->students[0]);
412 $submission = $assign->get_user_submission($this->students[0]->id, true);
413 $data = new stdClass();
414 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
415 'text'=>'Submission text',
416 'format'=>FORMAT_MOODLE);
417 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
418 $plugin->save($submission, $data);
419
420 $this->assertEquals(true, $assign->has_submissions_or_grades());
421 // Now try and reset.
422 $data = new stdClass();
423 $data->reset_assign_submissions = 1;
424 $data->reset_gradebook_grades = 1;
425 $data->courseid = $this->course->id;
426 $data->timeshift = 24*60*60;
427 $this->setUser($this->editingteachers[0]);
428 $assign->reset_userdata($data);
429 $this->assertEquals(false, $assign->has_submissions_or_grades());
430
431 // Reload the instance data.
432 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
433 $this->assertEquals($now + 24*60*60, $instance->duedate);
e63515ba
RT
434
435 // Test reset using assign_reset_userdata().
436 $assignduedate = $instance->duedate; // Keep old updated value for comparison.
437 $data->timeshift = 2*24*60*60;
438 assign_reset_userdata($data);
439 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
440 $this->assertEquals($assignduedate + 2*24*60*60, $instance->duedate);
441
442 // Create one more assignment and reset, make sure time shifted for previous assignment is not changed.
443 $assign2 = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1,
444 'duedate' => $now));
445 $assignduedate = $instance->duedate;
446 $data->timeshift = 3*24*60*60;
447 $assign2->reset_userdata($data);
448 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
449 $this->assertEquals($assignduedate, $instance->duedate);
450 $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id));
451 $this->assertEquals($now + 3*24*60*60, $instance2->duedate);
452
453 // Reset both assignments using assign_reset_userdata() and make sure both assignments have same date.
454 $assignduedate = $instance->duedate;
455 $assign2duedate = $instance2->duedate;
456 $data->timeshift = 4*24*60*60;
457 assign_reset_userdata($data);
458 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
459 $this->assertEquals($assignduedate + 4*24*60*60, $instance->duedate);
460 $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id));
461 $this->assertEquals($assign2duedate + 4*24*60*60, $instance2->duedate);
47f48152
DW
462 }
463
464 public function test_plugin_settings() {
465 global $DB;
466
467 $now = time();
468 $this->setUser($this->editingteachers[0]);
469 $assign = $this->create_instance(array('assignsubmission_file_enabled'=>1,
470 'assignsubmission_file_maxfiles'=>12,
471 'assignsubmission_file_maxsizebytes'=>10));
472
473 $plugin = $assign->get_submission_plugin_by_type('file');
474 $this->assertEquals('12', $plugin->get_config('maxfilesubmissions'));
475 }
476
477 public function test_update_calendar() {
478 global $DB;
479
47f48152 480 $this->setUser($this->editingteachers[0]);
f588ea50
FM
481 $userctx = context_user::instance($this->editingteachers[0]->id)->id;
482
483 // Hack to pretend that there was an editor involved. We need both $_POST and $_REQUEST, and a sesskey.
484 $draftid = file_get_unused_draft_itemid();
485 $_REQUEST['introeditor'] = $draftid;
486 $_POST['introeditor'] = $draftid;
487 $_POST['sesskey'] = sesskey();
488
489 // Write links to a draft area.
490 $fakearealink1 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">link</a>', 'draftfile.php', $userctx,
491 'user', 'draft', $draftid);
492 $fakearealink2 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">new</a>', 'draftfile.php', $userctx,
493 'user', 'draft', $draftid);
494
495 // Create a new assignment with links to a draft area.
496 $now = time();
497 $assign = $this->create_instance(array(
498 'duedate' => $now,
499 'intro' => $fakearealink1,
500 'introformat' => FORMAT_HTML
501 ));
47f48152
DW
502
503 // See if there is an event in the calendar.
504 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
f588ea50
FM
505 $event = $DB->get_record('event', $params);
506 $this->assertNotEmpty($event);
507 $this->assertSame('link', $event->description); // The pluginfile links are removed.
47f48152 508
f588ea50
FM
509 // Make sure the same works when updating the assignment.
510 $instance = $assign->get_instance();
511 $instance->instance = $instance->id;
512 $instance->intro = $fakearealink2;
513 $instance->introformat = FORMAT_HTML;
514 $assign->update_instance($instance);
515 $params = array('modulename' => 'assign', 'instance' => $assign->get_instance()->id);
516 $event = $DB->get_record('event', $params);
517 $this->assertNotEmpty($event);
518 $this->assertSame('new', $event->description); // The pluginfile links are removed.
ae7638f7
DW
519
520 // Create an assignment with a description that should be hidden.
521 $assign = $this->create_instance(array('duedate'=>$now + 160,
522 'alwaysshowdescription'=>false,
8112670d 523 'allowsubmissionsfromdate'=>$now + 60,
ae7638f7
DW
524 'intro'=>'Some text'));
525
526 // Get the event from the calendar.
527 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
528 $event = $DB->get_record('event', $params);
529
530 $this->assertEmpty($event->description);
8112670d
DW
531
532 // Change the allowsubmissionfromdate to the past - do this directly in the DB
533 // because if we call the assignment update method - it will update the calendar
534 // and we want to test that this works from cron.
535 $DB->set_field('assign', 'allowsubmissionsfromdate', $now - 60, array('id'=>$assign->get_instance()->id));
ae7638f7
DW
536 // Run cron to update the event in the calendar.
537 assign::cron();
538 $event = $DB->get_record('event', $params);
539
540 $this->assertContains('Some text', $event->description);
541
47f48152
DW
542 }
543
544 public function test_update_instance() {
545 global $DB;
546
547 $this->setUser($this->editingteachers[0]);
548 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
549
550 $now = time();
551 $instance = $assign->get_instance();
552 $instance->duedate = $now;
553 $instance->instance = $instance->id;
554 $instance->assignsubmission_onlinetext_enabled = 1;
47f48152
DW
555
556 $assign->update_instance($instance);
557
558 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
559 $this->assertEquals($now, $instance->duedate);
560 }
561
8fd00a24
DW
562 public function test_cannot_submit_empty() {
563 global $PAGE;
564
565 $this->setUser($this->editingteachers[0]);
566 $assign = $this->create_instance(array('submissiondrafts'=>1));
567
568 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
569
570 // Test you cannot see the submit button for an offline assignment regardless.
571 $this->setUser($this->students[0]);
572 $output = $assign->view_student_summary($this->students[0], true);
573 $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Can submit empty offline assignment');
574
575 // Test you cannot see the submit button for an online text assignment with no submission.
576 $this->setUser($this->editingteachers[0]);
577 $instance = $assign->get_instance();
578 $instance->instance = $instance->id;
579 $instance->assignsubmission_onlinetext_enabled = 1;
580
581 $assign->update_instance($instance);
582 $this->setUser($this->students[0]);
583 $output = $assign->view_student_summary($this->students[0], true);
584 $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Cannot submit empty onlinetext assignment');
585
586 // Simulate a submission.
587 $submission = $assign->get_user_submission($this->students[0]->id, true);
588 $data = new stdClass();
589 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
590 'text'=>'Submission text',
591 'format'=>FORMAT_MOODLE);
592 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
593 $plugin->save($submission, $data);
594 // Test you can see the submit button for an online text assignment with a submission.
595 $output = $assign->view_student_summary($this->students[0], true);
596 $this->assertContains(get_string('submitassignment', 'assign'), $output, 'Can submit non empty onlinetext assignment');
597 }
598
47f48152 599 public function test_list_participants() {
c13ac85d 600 global $CFG, $DB;
601
df211804 602 $this->create_extra_users();
47f48152
DW
603 $this->setUser($this->editingteachers[0]);
604 $assign = $this->create_instance(array('grade'=>100));
605
a5c793c3 606 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
e6cc5347
RT
607
608 // Teacher with user preference set should see suspended users as well.
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 + self::EXTRA_SUSPENDED_COUNT,
612 count($assign->list_participants(null, true)));
613
1ecb8044 614 // Non-editing teacher should not see suspended users, even if user preference is set.
e6cc5347
RT
615 $this->setUser($this->teachers[0]);
616 set_user_preference('grade_report_showonlyactiveenrol', false);
617 $assign = $this->create_instance(array('grade'=>100));
618 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
c13ac85d 619
620 // Turn on availability and a group restriction, and check that it doesn't
621 // show users who aren't in the group.
622 $CFG->enableavailability = true;
623 $specialgroup = $this->getDataGenerator()->create_group(
624 array('courseid' => $this->course->id));
625 $assign = $this->create_instance(array('grade' => 100,
626 'availability' => json_encode(\core_availability\tree::get_root_json(
627 array(\availability_group\condition::get_json($specialgroup->id))))));
628 groups_add_member($specialgroup, $this->students[0]);
629 groups_add_member($specialgroup, $this->students[1]);
630 $this->assertEquals(2, count($assign->list_participants(null, true)));
47f48152
DW
631 }
632
633 public function test_count_teams() {
df211804 634 $this->create_extra_users();
47f48152 635 $this->setUser($this->editingteachers[0]);
2dda9417
DM
636 $assign1 = $this->create_instance(array('teamsubmission' => 1));
637 $this->assertEquals(self::GROUP_COUNT + 1, $assign1->count_teams());
47f48152 638
2dda9417
DM
639 $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id));
640 $this->getDataGenerator()->create_grouping_group(array('groupid' => $this->groups[0]->id, 'groupingid' => $grouping->id));
641 $this->getDataGenerator()->create_grouping_group(array('groupid' => $this->groups[1]->id, 'groupingid' => $grouping->id));
642
643 // No active group => 2 groups + the default one.
644 $assign2 = $this->create_instance(array('teamsubmission' => 1, 'teamsubmissiongroupingid' => $grouping->id));
645 $this->assertEquals(3, $assign2->count_teams());
646
647 // An active group => Just the selected one.
648 $this->assertEquals(1, $assign2->count_teams($this->groups[0]->id));
47f48152
DW
649 }
650
e2d2d8a1 651 public function test_submit_to_default_group() {
2dda9417 652 global $DB, $SESSION;
e2d2d8a1
DW
653
654 $this->preventResetByRollback();
655 $sink = $this->redirectMessages();
656
657 $this->setUser($this->editingteachers[0]);
658 $params = array('teamsubmission' => 1,
659 'assignsubmission_onlinetext_enabled' => 1,
2dda9417
DM
660 'submissiondrafts' => 0,
661 'groupmode' => VISIBLEGROUPS);
e2d2d8a1
DW
662 $assign = $this->create_instance($params);
663
664 $newstudent = $this->getDataGenerator()->create_user();
665 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
666 $this->getDataGenerator()->enrol_user($newstudent->id,
667 $this->course->id,
668 $studentrole->id);
669 $this->setUser($newstudent);
670 $data = new stdClass();
671 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
672 'text'=>'Submission text',
673 'format'=>FORMAT_MOODLE);
674 $notices = array();
675
676 $group = $assign->get_submission_group($newstudent->id);
677 $this->assertFalse($group, 'New student is in default group');
678 $assign->save_submission($data, $notices);
679 $this->assertEmpty($notices, 'No errors on save submission');
680
2dda9417
DM
681 // Set active groups to all groups.
682 $this->setUser($this->teachers[0]);
683 $SESSION->activegroup[$this->course->id]['aag'][0] = 0;
684 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
685
686 // Set an active group.
687 $anothergroup = $this->groups[0];
688 $SESSION->activegroup[$this->course->id]['aag'][0] = (int)$anothergroup->id;
689 $this->assertEquals(0, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
690
e2d2d8a1
DW
691 $sink->close();
692 }
693
47f48152 694 public function test_count_submissions() {
2dda9417
DM
695 global $SESSION;
696
df211804 697 $this->create_extra_users();
47f48152 698 $this->setUser($this->editingteachers[0]);
2dda9417 699 $assign1 = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1));
47f48152
DW
700
701 // Simulate a submission.
a5c793c3 702 $this->setUser($this->extrastudents[0]);
2dda9417 703 $submission = $assign1->get_user_submission($this->extrastudents[0]->id, true);
9e3eee67 704 $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
2dda9417 705 $assign1->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
706 // Leave this one as DRAFT.
707 $data = new stdClass();
708 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
709 'text'=>'Submission text',
710 'format'=>FORMAT_MOODLE);
2dda9417 711 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
47f48152
DW
712 $plugin->save($submission, $data);
713
714 // Simulate adding a grade.
715 $this->setUser($this->teachers[0]);
716 $data = new stdClass();
717 $data->grade = '50.0';
2dda9417 718 $assign1->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0);
47f48152
DW
719
720 // Simulate a submission.
a5c793c3 721 $this->setUser($this->extrastudents[1]);
2dda9417 722 $submission = $assign1->get_user_submission($this->extrastudents[1]->id, true);
47f48152 723 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2dda9417 724 $assign1->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
47f48152
DW
725 $data = new stdClass();
726 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
727 'text'=>'Submission text',
728 'format'=>FORMAT_MOODLE);
2dda9417 729 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
47f48152
DW
730 $plugin->save($submission, $data);
731
732 // Simulate a submission.
a5c793c3 733 $this->setUser($this->extrastudents[2]);
2dda9417 734 $submission = $assign1->get_user_submission($this->extrastudents[2]->id, true);
47f48152 735 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2dda9417 736 $assign1->testable_update_submission($submission, $this->extrastudents[2]->id, true, false);
47f48152
DW
737 $data = new stdClass();
738 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
739 'text'=>'Submission text',
740 'format'=>FORMAT_MOODLE);
2dda9417 741 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
47f48152
DW
742 $plugin->save($submission, $data);
743
744 // Simulate a submission.
a5c793c3 745 $this->setUser($this->extrastudents[3]);
2dda9417 746 $submission = $assign1->get_user_submission($this->extrastudents[3]->id, true);
47f48152 747 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2dda9417 748 $assign1->testable_update_submission($submission, $this->extrastudents[3]->id, true, false);
47f48152
DW
749 $data = new stdClass();
750 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
751 'text'=>'Submission text',
752 'format'=>FORMAT_MOODLE);
2dda9417 753 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
47f48152
DW
754 $plugin->save($submission, $data);
755
e6cc5347
RT
756 // Simulate a submission for suspended user, this will never be counted.
757 $this->setUser($this->extrastudents[3]);
2dda9417 758 $submission = $assign1->get_user_submission($this->extrasuspendedstudents[0]->id, true);
e6cc5347 759 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2dda9417 760 $assign1->testable_update_submission($submission, $this->extrasuspendedstudents[0]->id, true, false);
e6cc5347
RT
761 $data = new stdClass();
762 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
763 'text'=>'Submission text',
764 'format'=>FORMAT_MOODLE);
2dda9417 765 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
e6cc5347
RT
766 $plugin->save($submission, $data);
767
47f48152
DW
768 // Simulate adding a grade.
769 $this->setUser($this->teachers[0]);
770 $data = new stdClass();
771 $data->grade = '50.0';
2dda9417
DM
772 $assign1->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0);
773 $assign1->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0);
47f48152 774
ab14ab74
FM
775 // Create a new submission with status NEW.
776 $this->setUser($this->extrastudents[4]);
2dda9417
DM
777 $submission = $assign1->get_user_submission($this->extrastudents[4]->id, true);
778
779 $this->assertEquals(2, $assign1->count_grades());
780 $this->assertEquals(4, $assign1->count_submissions());
781 $this->assertEquals(5, $assign1->count_submissions(true));
782 $this->assertEquals(2, $assign1->count_submissions_need_grading());
783 $this->assertEquals(3, $assign1->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
784 $this->assertEquals(1, $assign1->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
785
786 // Groups.
787 $assign2 = $this->create_instance(array(
788 'assignsubmission_onlinetext_enabled' => 1,
789 'groupmode' => VISIBLEGROUPS
790 ));
791
792 $this->setUser($this->extrastudents[1]);
793 $submission = $assign2->get_user_submission($this->extrastudents[1]->id, true);
794 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
795 $assign2->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
796 $data = new stdClass();
797 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
798 'text' => 'Submission text',
799 'format' => FORMAT_MOODLE);
800 $plugin = $assign2->get_submission_plugin_by_type('onlinetext');
801 $plugin->save($submission, $data);
802
803 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
804
805 // Set active groups to all groups.
806 $this->setUser($this->teachers[0]);
807 $SESSION->activegroup[$this->course->id]['aag'][0] = 0;
808 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
809
810 // Set the user group.
811 $studentgroups = groups_get_user_groups($this->course->id, $this->extrastudents[1]->id);
812 $this->assertEquals(1, count($studentgroups));
813 $studentgroup = array_pop($studentgroups);
814 $SESSION->activegroup[$this->course->id]['aag'][0] = $studentgroup[0];
815 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
816
817 // Set another group.
818 $anothergroup = $this->groups[0];
819 $this->assertNotEquals($anothergroup->id, $studentgroup[0]);
820 $SESSION->activegroup[$this->course->id]['aag'][0] = (int)$anothergroup->id;
821 $this->assertEquals(0, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
47f48152
DW
822 }
823
ab14ab74
FM
824 public function test_count_submissions_for_groups() {
825 $this->create_extra_users();
826 $groupid = null;
827 $this->setUser($this->editingteachers[0]);
828 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1, 'teamsubmission' => 1));
829
830 // Simulate a submission.
831 $this->setUser($this->extrastudents[0]);
832 $submission = $assign->get_group_submission($this->extrastudents[0]->id, $groupid, true);
833 $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
834 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
835 // Leave this one as DRAFT.
836 $data = new stdClass();
837 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
838 'text' => 'Submission text',
839 'format' => FORMAT_MOODLE);
840 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
841 $plugin->save($submission, $data);
842
843 // Simulate adding a grade.
844 $this->setUser($this->teachers[0]);
845 $data = new stdClass();
846 $data->grade = '50.0';
847 $assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0);
848
849 // Simulate a submission.
850 $this->setUser($this->extrastudents[1]);
851 $submission = $assign->get_group_submission($this->extrastudents[1]->id, $groupid, true);
852 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
853 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
854 $data = new stdClass();
855 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
856 'text' => 'Submission text',
857 'format' => FORMAT_MOODLE);
858 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
859 $plugin->save($submission, $data);
860
861 // Simulate a submission.
862 $this->setUser($this->extrastudents[2]);
863 $submission = $assign->get_group_submission($this->extrastudents[2]->id, $groupid, true);
864 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
865 $assign->testable_update_submission($submission, $this->extrastudents[2]->id, true, false);
866 $data = new stdClass();
867 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
868 'text' => 'Submission text',
869 'format' => FORMAT_MOODLE);
870 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
871 $plugin->save($submission, $data);
872
873 // Simulate a submission.
874 $this->setUser($this->extrastudents[3]);
875 $submission = $assign->get_group_submission($this->extrastudents[3]->id, $groupid, true);
876 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
877 $assign->testable_update_submission($submission, $this->extrastudents[3]->id, true, false);
878 $data = new stdClass();
879 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
880 'text' => 'Submission text',
881 'format' => FORMAT_MOODLE);
882 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
883 $plugin->save($submission, $data);
884
885 // Simulate adding a grade.
886 $this->setUser($this->teachers[0]);
887 $data = new stdClass();
888 $data->grade = '50.0';
889 $assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0);
890 $assign->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0);
891
892 // Create a new submission with status NEW.
893 $this->setUser($this->extrastudents[4]);
894 $submission = $assign->get_group_submission($this->extrastudents[4]->id, $groupid, true);
895
896 $this->assertEquals(2, $assign->count_grades());
897 $this->assertEquals(4, $assign->count_submissions());
898 $this->assertEquals(5, $assign->count_submissions(true));
899 $this->assertEquals(3, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
900 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
901 }
902
47f48152 903 public function test_get_grading_userid_list() {
df211804 904 $this->create_extra_users();
47f48152
DW
905 $this->setUser($this->editingteachers[0]);
906 $assign = $this->create_instance();
907
908 $users = $assign->testable_get_grading_userid_list();
a5c793c3 909 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($users));
e6cc5347
RT
910
911 $this->setUser($this->editingteachers[0]);
912 set_user_preference('grade_report_showonlyactiveenrol', false);
913 $assign = $this->create_instance();
914
915 $users = $assign->testable_get_grading_userid_list();
916 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT, count($users));
47f48152
DW
917 }
918
919 public function test_cron() {
920 // First run cron so there are no messages waiting to be sent (from other tests).
921 cron_setup_user();
922 assign::cron();
923
924 // Now create an assignment and add some feedback.
925 $this->setUser($this->editingteachers[0]);
8e1266bf 926 $assign = $this->create_instance(array('sendstudentnotifications'=>1));
47f48152
DW
927
928 // Simulate adding a grade.
929 $this->setUser($this->teachers[0]);
930 $data = new stdClass();
931 $data->grade = '50.0';
df211804 932 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
4d2bd673 933 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
47f48152 934
f7dc9871
DW
935 $data->sendstudentnotifications = false;
936 $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0);
937
47f48152
DW
938 // Now run cron and see that one message was sent.
939 $this->preventResetByRollback();
940 $sink = $this->redirectMessages();
941 cron_setup_user();
4d2bd673 942 $this->expectOutputRegex('/Done processing 2 assignment submissions/');
47f48152
DW
943 assign::cron();
944
945 $messages = $sink->get_messages();
f7dc9871 946 // The sent count should be 2, because the 3rd one was marked as do not send notifications.
4d2bd673 947 $this->assertEquals(2, count($messages));
47f48152
DW
948 $this->assertEquals(1, $messages[0]->notification);
949 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
a4b10a52
ZD
950
951 // Regrading a grade causes a notification to the user.
952 $data->sendstudentnotifications = true;
953 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
954 assign::cron();
955 $messages = $sink->get_messages();
956 $this->assertEquals(3, count($messages));
47f48152
DW
957 }
958
70cfc878
JF
959 /**
960 * Test delivery of grade notifications as controlled by marking workflow.
961 */
962 public function test_markingworkflow_cron() {
963 // First run cron so there are no messages waiting to be sent (from other tests).
964 cron_setup_user();
965 assign::cron();
966
967 // Now create an assignment with marking workflow enabled.
968 $this->setUser($this->editingteachers[0]);
969 $assign = $this->create_instance(array('sendstudentnotifications' => 1, 'markingworkflow' => 1));
970
971 // Simulate adding a grade.
972 $this->setUser($this->teachers[0]);
973 $data = new stdClass();
974 $data->grade = '50.0';
975
976 // This student will not receive notification.
977 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE;
978 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
979
980 // This student will receive notification.
981 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED;
982 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
983
984 // Now run cron and see that one message was sent.
985 $this->preventResetByRollback();
986 $sink = $this->redirectMessages();
987 cron_setup_user();
988 $this->expectOutputRegex('/Done processing 1 assignment submissions/');
989 assign::cron();
990
991 $messages = $sink->get_messages();
992 $this->assertEquals(1, count($messages));
993 $this->assertEquals($messages[0]->useridto, $this->students[1]->id);
994 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
995 }
996
47f48152
DW
997 public function test_is_graded() {
998 $this->setUser($this->editingteachers[0]);
999 $assign = $this->create_instance();
1000
1001 // Simulate adding a grade.
1002 $this->setUser($this->teachers[0]);
1003 $data = new stdClass();
1004 $data->grade = '50.0';
df211804 1005 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
1006
1007 $this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id));
1008 $this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
1009 }
1010
4a47008c
DW
1011 public function test_can_grade() {
1012 global $DB;
1013
1014 $this->setUser($this->editingteachers[0]);
1015 $assign = $this->create_instance();
1016
1017 $this->setUser($this->students[0]);
1018 $this->assertEquals(false, $assign->can_grade());
1019 $this->setUser($this->editingteachers[0]);
1020 $this->assertEquals(true, $assign->can_grade());
1021 $this->setUser($this->teachers[0]);
1022 $this->assertEquals(true, $assign->can_grade());
1023
1024 // Test the viewgrades capability - without mod/assign:grade.
1025 $this->setUser($this->students[0]);
1026 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1027 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
1028 $this->assertEquals(false, $assign->can_grade());
1029 }
1030
47f48152 1031 public function test_can_view_submission() {
4a47008c
DW
1032 global $DB;
1033
e6cc5347 1034 $this->create_extra_users();
47f48152
DW
1035 $this->setUser($this->editingteachers[0]);
1036 $assign = $this->create_instance();
1037
1038 $this->setUser($this->students[0]);
1039 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
1040 $this->assertEquals(false, $assign->can_view_submission($this->students[1]->id));
1041 $this->assertEquals(false, $assign->can_view_submission($this->teachers[0]->id));
1042 $this->setUser($this->teachers[0]);
1043 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
1044 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
1045 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
e6cc5347 1046 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
47f48152
DW
1047 $this->setUser($this->editingteachers[0]);
1048 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
1049 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
1050 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
e6cc5347 1051 $this->assertEquals(true, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
4a47008c
DW
1052
1053 // Test the viewgrades capability - without mod/assign:grade.
1054 $this->setUser($this->students[0]);
1055 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1056 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
1057 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
1058 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
1059 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
1060 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
47f48152
DW
1061 }
1062
1063
1064 public function test_update_submission() {
df211804 1065 $this->create_extra_users();
47f48152
DW
1066 $this->setUser($this->editingteachers[0]);
1067 $assign = $this->create_instance();
1068
a5c793c3 1069 $this->setUser($this->extrastudents[0]);
47f48152 1070 $now = time();
a5c793c3
DW
1071 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
1072 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
1073
1074 $this->setUser($this->teachers[0]);
1075 // Verify the gradebook update.
1076 $gradinginfo = grade_get_grades($this->course->id,
1077 'mod',
1078 'assign',
1079 $assign->get_instance()->id,
a5c793c3 1080 $this->extrastudents[0]->id);
47f48152 1081
a5c793c3
DW
1082 $this->assertEquals($this->extrastudents[0]->id,
1083 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
47f48152
DW
1084
1085 // Now verify group assignments.
1086 $this->setUser($this->editingteachers[0]);
1087 $assign = $this->create_instance(array('teamsubmission'=>1));
1088
a5c793c3 1089 $this->setUser($this->extrastudents[0]);
47f48152 1090 $now = time();
a5c793c3
DW
1091 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1092 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
47f48152 1093
e6cc5347 1094 // Check that at least 2 active members and 1 suspended member of the submission group had their submission updated.
47f48152
DW
1095
1096 $this->setUser($this->editingteachers[0]);
1097 $gradinginfo = grade_get_grades($this->course->id,
1098 'mod',
1099 'assign',
1100 $assign->get_instance()->id,
a5c793c3 1101 $this->extrastudents[0]->id);
47f48152 1102
a5c793c3
DW
1103 $this->assertEquals($this->extrastudents[0]->id,
1104 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
47f48152
DW
1105
1106 $gradinginfo = grade_get_grades($this->course->id,
1107 'mod',
1108 'assign',
1109 $assign->get_instance()->id,
a5c793c3 1110 $this->extrastudents[self::GROUP_COUNT]->id);
47f48152 1111
a5c793c3
DW
1112 $this->assertEquals($this->extrastudents[self::GROUP_COUNT]->id,
1113 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT]->id]->usermodified);
47f48152 1114
e6cc5347
RT
1115 $gradinginfo = grade_get_grades($this->course->id,
1116 'mod',
1117 'assign',
1118 $assign->get_instance()->id,
1119 $this->extrasuspendedstudents[0]->id);
1120 $this->assertEquals($this->extrasuspendedstudents[0]->id,
1121 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[0]->id]->usermodified);
1122
1123 // Check the same with non-editing teacher and make sure submission is not updated for suspended user.
1124 $this->setUser($this->editingteachers[0]);
1125 $assign = $this->create_instance(array('teamsubmission'=>1));
1126
1127 $this->setUser($this->extrastudents[1]);
1128 $now = time();
1129 $submission = $assign->get_group_submission($this->extrastudents[1]->id, 0, true);
1130 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, true);
1131
1132 $this->setUser($this->teachers[0]);
1133 $gradinginfo = grade_get_grades($this->course->id,
1134 'mod',
1135 'assign',
1136 $assign->get_instance()->id,
1137 $this->extrastudents[1]->id);
1138
1139 $this->assertEquals($this->extrastudents[1]->id,
1140 $gradinginfo->items[0]->grades[$this->extrastudents[1]->id]->usermodified);
1141
1142 $gradinginfo = grade_get_grades($this->course->id,
1143 'mod',
1144 'assign',
1145 $assign->get_instance()->id,
1146 $this->extrastudents[self::GROUP_COUNT+1]->id);
1147
1148 $this->assertEquals($this->extrastudents[self::GROUP_COUNT+1]->id,
1149 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT+1]->id]->usermodified);
1150
1151 $gradinginfo = grade_get_grades($this->course->id,
1152 'mod',
1153 'assign',
1154 $assign->get_instance()->id,
1155 $this->extrasuspendedstudents[1]->id);
1156 $this->assertEquals($this->extrasuspendedstudents[1]->id,
1157 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[1]->id]->usermodified);
1158
47f48152
DW
1159 // Now verify blind marking.
1160 $this->setUser($this->editingteachers[0]);
1161 $assign = $this->create_instance(array('blindmarking'=>1));
1162
a5c793c3 1163 $this->setUser($this->extrastudents[0]);
47f48152 1164 $now = time();
a5c793c3
DW
1165 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
1166 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
1167
1168 $this->setUser($this->editingteachers[0]);
1169 $gradinginfo = grade_get_grades($this->course->id,
1170 'mod',
1171 'assign',
1172 $assign->get_instance()->id,
a5c793c3 1173 $this->extrastudents[0]->id);
47f48152 1174
a5c793c3 1175 $this->assertEquals(null, $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->datesubmitted);
47f48152
DW
1176 }
1177
79397b56 1178 public function test_group_submissions_submit_for_marking_requireallteammemberssubmit() {
2bd27878
DW
1179 global $PAGE;
1180
1181 $this->create_extra_users();
1182 // Now verify group assignments.
1183 $this->setUser($this->editingteachers[0]);
1184 $assign = $this->create_instance(array('teamsubmission'=>1,
1185 'assignsubmission_onlinetext_enabled'=>1,
1186 'submissiondrafts'=>1,
1187 'requireallteammemberssubmit'=>1));
1188 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1189
2bd27878 1190 // Add a submission.
79397b56 1191 $this->setUser($this->extrastudents[0]);
2bd27878
DW
1192 $data = new stdClass();
1193 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1194 'text'=>'Submission text',
1195 'format'=>FORMAT_MOODLE);
1196
1197 $notices = array();
1198 $assign->save_submission($data, $notices);
1199
1200 // Check we can see the submit button.
1201 $output = $assign->view_student_summary($this->extrastudents[0], true);
1202 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1203
1204 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1205 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1206 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
1207
1208 // Check that the student does not see "Submit" button.
1209 $output = $assign->view_student_summary($this->extrastudents[0], true);
1210 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1211
1212 // Change to another user in the same group.
1213 $this->setUser($this->extrastudents[self::GROUP_COUNT]);
1214 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1215 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1216
1217 $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
1218 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1219 $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
1220 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1221 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1222 }
1223
79397b56
DB
1224 public function test_group_submissions_submit_for_marking() {
1225 global $PAGE;
1226
1227 $this->create_extra_users();
1228 // Now verify group assignments.
1229 $this->setUser($this->editingteachers[0]);
a0f8db77 1230 $time = time();
79397b56
DB
1231 $assign = $this->create_instance(array('teamsubmission'=>1,
1232 'assignsubmission_onlinetext_enabled'=>1,
1233 'submissiondrafts'=>1,
1234 'requireallteammemberssubmit'=>0,
a0f8db77 1235 'duedate' => $time - 2*24*60*60));
79397b56
DB
1236 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1237
1238 $this->setUser($this->extrastudents[0]);
1239 // Add a submission.
1240 $data = new stdClass();
1241 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1242 'text'=>'Submission text',
1243 'format'=>FORMAT_MOODLE);
1244
1245 $notices = array();
1246 $assign->save_submission($data, $notices);
1247
1248 // Check we can see the submit button.
1249 $output = $assign->view_student_summary($this->extrastudents[0], true);
1250 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1251 $this->assertContains(get_string('timeremaining', 'assign'), $output);
a0f8db77
DW
1252 $difftime = time() - $time;
1253 $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60 + $difftime)), $output);
79397b56
DB
1254
1255 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1256 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1257 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
1258
1259 // Check that the student does not see "Submit" button.
1260 $output = $assign->view_student_summary($this->extrastudents[0], true);
1261 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1262
1263 // Change to another user in the same group.
1264 $this->setUser($this->extrastudents[self::GROUP_COUNT]);
1265 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1266 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1267
1268 // Check that time remaining is not overdue.
1269 $this->assertContains(get_string('timeremaining', 'assign'), $output);
a0f8db77
DW
1270 $difftime = time() - $time;
1271 $this->assertContains(get_string('submittedlate', 'assign', format_time(2*24*60*60 + $difftime)), $output);
79397b56
DB
1272
1273 $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
1274 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1275 $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
1276 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1277 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1278 }
1279
47f48152
DW
1280 public function test_submissions_open() {
1281 $this->setUser($this->editingteachers[0]);
1282
1283 $now = time();
1284 $tomorrow = $now + 24*60*60;
1285 $oneweek = $now + 7*24*60*60;
1286 $yesterday = $now - 24*60*60;
1287
1288 $assign = $this->create_instance();
1289 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1290
1291 $assign = $this->create_instance(array('duedate'=>$tomorrow));
1292 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1293
1294 $assign = $this->create_instance(array('duedate'=>$yesterday));
1295 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1296
1297 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$tomorrow));
1298 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1299
1300 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$yesterday));
1301 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
1302
1303 $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
1304 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1305
1306 $assign = $this->create_instance(array('submissiondrafts'=>1));
1307 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1308
1309 $this->setUser($this->students[0]);
1310 $now = time();
1311 $submission = $assign->get_user_submission($this->students[0]->id, true);
1312 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1313 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1314 $this->setUser($this->editingteachers[0]);
1315 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
1316 }
1317
1318 public function test_get_graders() {
df211804 1319 $this->create_extra_users();
47f48152 1320 $this->setUser($this->editingteachers[0]);
47f48152 1321
f268fb5d
DW
1322 // Create an assignment with no groups.
1323 $assign = $this->create_instance();
a5c793c3
DW
1324 $this->assertCount(self::DEFAULT_TEACHER_COUNT +
1325 self::DEFAULT_EDITING_TEACHER_COUNT +
1326 self::EXTRA_TEACHER_COUNT +
1327 self::EXTRA_EDITING_TEACHER_COUNT,
1328 $assign->testable_get_graders($this->students[0]->id));
47f48152 1329
47f48152 1330 // Force create an assignment with SEPARATEGROUPS.
f268fb5d
DW
1331 $data = new stdClass();
1332 $data->courseid = $this->course->id;
1333 $data->name = 'Grouping';
1334 $groupingid = groups_create_grouping($data);
1335 groups_assign_grouping($groupingid, $this->groups[0]->id);
1336 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
47f48152
DW
1337
1338 $this->setUser($this->students[1]);
a5c793c3 1339 $this->assertCount(4, $assign->testable_get_graders($this->students[0]->id));
f268fb5d
DW
1340 // Note the second student is in a group that is not in the grouping.
1341 // This means that we get all graders that are not in a group in the grouping.
1342 $this->assertCount(10, $assign->testable_get_graders($this->students[1]->id));
47f48152
DW
1343 }
1344
83360c8d
S
1345 public function test_get_notified_users() {
1346 global $CFG, $DB;
1347
1348 $capability = 'mod/assign:receivegradernotifications';
1349 $coursecontext = context_course::instance($this->course->id);
1350 $role = $DB->get_record('role', array('shortname' => 'teacher'));
1351
1352 $this->create_extra_users();
1353 $this->setUser($this->editingteachers[0]);
1354
1355 // Create an assignment with no groups.
1356 $assign = $this->create_instance();
1357
1358 $this->assertCount(self::DEFAULT_TEACHER_COUNT +
1359 self::DEFAULT_EDITING_TEACHER_COUNT +
1360 self::EXTRA_TEACHER_COUNT +
1361 self::EXTRA_EDITING_TEACHER_COUNT,
1362 $assign->testable_get_notifiable_users($this->students[0]->id));
1363
1364 // Change nonediting teachers role to not receive grader notifications.
1365 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
1366
1367 $this->assertCount(self::DEFAULT_EDITING_TEACHER_COUNT +
1368 self::EXTRA_EDITING_TEACHER_COUNT,
1369 $assign->testable_get_notifiable_users($this->students[0]->id));
1370
1371 // Reset nonediting teachers role to default.
1372 unassign_capability($capability, $role->id, $coursecontext);
1373
1374 // Force create an assignment with SEPARATEGROUPS.
1375 $data = new stdClass();
1376 $data->courseid = $this->course->id;
1377 $data->name = 'Grouping';
1378 $groupingid = groups_create_grouping($data);
1379 groups_assign_grouping($groupingid, $this->groups[0]->id);
1380 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
1381
1382 $this->setUser($this->students[1]);
1383 $this->assertCount(4, $assign->testable_get_notifiable_users($this->students[0]->id));
1384 // Note the second student is in a group that is not in the grouping.
1385 // This means that we get all graders that are not in a group in the grouping.
1386 $this->assertCount(10, $assign->testable_get_notifiable_users($this->students[1]->id));
1387
1388 // Change nonediting teachers role to not receive grader notifications.
1389 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
1390
1391 $this->assertCount(2, $assign->testable_get_notifiable_users($this->students[0]->id));
1392 // Note the second student is in a group that is not in the grouping.
1393 // This means that we get all graders that are not in a group in the grouping.
1394 $this->assertCount(5, $assign->testable_get_notifiable_users($this->students[1]->id));
1395 }
1396
20b7dcfc
DW
1397 public function test_group_members_only() {
1398 global $CFG;
1399
1400 $this->setAdminUser();
1401 $this->create_extra_users();
c13ac85d 1402 $CFG->enableavailability = true;
20b7dcfc
DW
1403 $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id));
1404 groups_assign_grouping($grouping->id, $this->groups[0]->id);
1405
1406 // Force create an assignment with SEPARATEGROUPS.
1407 $instance = $this->getDataGenerator()->create_module('assign', array('course'=>$this->course->id),
c13ac85d 1408 array('availability' => json_encode(\core_availability\tree::get_root_json(array(
1409 \availability_grouping\condition::get_json()))),
1410 'groupingid' => $grouping->id));
20b7dcfc
DW
1411
1412 $cm = get_coursemodule_from_instance('assign', $instance->id);
1413 $context = context_module::instance($cm->id);
1414 $assign = new testable_assign($context, $cm, $this->course);
1415
1416 $this->setUser($this->teachers[0]);
8270f0d0 1417 get_fast_modinfo($this->course, 0, true);
20b7dcfc
DW
1418 $this->assertCount(5, $assign->list_participants(0, true));
1419
1420 }
1421
47f48152
DW
1422 public function test_get_uniqueid_for_user() {
1423 $this->setUser($this->editingteachers[0]);
1424 $assign = $this->create_instance();
1425
1426 foreach ($this->students as $student) {
1427 $uniqueid = $assign->get_uniqueid_for_user($student->id);
1428 $this->assertEquals($student->id, $assign->get_user_id_for_uniqueid($uniqueid));
1429 }
1430 }
1431
46692c3a 1432 public function test_show_student_summary() {
c2114099 1433 global $CFG, $PAGE;
46692c3a
DW
1434
1435 $this->setUser($this->editingteachers[0]);
1436 $assign = $this->create_instance();
c2114099 1437 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
46692c3a
DW
1438
1439 // No feedback should be available because this student has not been graded.
1440 $this->setUser($this->students[0]);
1441 $output = $assign->view_student_summary($this->students[0], true);
1442 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if there is no grade');
1443 // Simulate adding a grade.
1444 $this->setUser($this->teachers[0]);
1445 $data = new stdClass();
1446 $data->grade = '50.0';
df211804 1447 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
46692c3a 1448
b0da618b 1449 // Now we should see the feedback.
46692c3a
DW
1450 $this->setUser($this->students[0]);
1451 $output = $assign->view_student_summary($this->students[0], true);
1452 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback if there is a grade');
1453
1454 // Now hide the grade in gradebook.
1455 $this->setUser($this->teachers[0]);
1456 require_once($CFG->libdir.'/gradelib.php');
1457 $gradeitem = new grade_item(array(
1458 'itemtype' => 'mod',
1459 'itemmodule' => 'assign',
1460 'iteminstance' => $assign->get_instance()->id,
1461 'courseid' => $this->course->id));
1462
1463 $gradeitem->set_hidden(1, false);
1464
1465 // No feedback should be available because the grade is hidden.
1466 $this->setUser($this->students[0]);
1467 $output = $assign->view_student_summary($this->students[0], true);
1468 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
1469
b0da618b 1470 // Do the same but add feedback.
46692c3a
DW
1471 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
1472
1473 $this->setUser($this->teachers[0]);
1474 $grade = $assign->get_user_grade($this->students[0]->id, true);
1475 $data = new stdClass();
1476 $data->assignfeedbackcomments_editor = array('text'=>'Tomato sauce',
1477 'format'=>FORMAT_MOODLE);
1478 $plugin = $assign->get_feedback_plugin_by_type('comments');
1479 $plugin->save($grade, $data);
1480
b0da618b 1481 // Should have feedback but no grade.
46692c3a
DW
1482 $this->setUser($this->students[0]);
1483 $output = $assign->view_student_summary($this->students[0], true);
ea698284 1484 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback even if there is no grade');
46692c3a
DW
1485 $this->assertEquals(false, strpos($output, 'Grade'), 'Do not show grade when there is no grade.');
1486 $this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.');
45aac51a 1487
ea698284
AD
1488 // Now hide the grade in gradebook.
1489 $this->setUser($this->teachers[0]);
1490 $gradeitem = new grade_item(array(
1491 'itemtype' => 'mod',
1492 'itemmodule' => 'assign',
1493 'iteminstance' => $assign->get_instance()->id,
1494 'courseid' => $this->course->id));
1495
1496 $gradeitem->set_hidden(1, false);
1497
1498 // No feedback should be available because the grade is hidden.
1499 $this->setUser($this->students[0]);
1500 $output = $assign->view_student_summary($this->students[0], true);
1501 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
46692c3a
DW
1502 }
1503
df211804
DW
1504 public function test_attempt_reopen_method_manual() {
1505 global $PAGE;
1506
1507 $this->setUser($this->editingteachers[0]);
1508 $assign = $this->create_instance(array('attemptreopenmethod'=>ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
1509 'maxattempts'=>3,
1510 'submissiondrafts'=>1,
1511 'assignsubmission_onlinetext_enabled'=>1));
1512 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1513
1514 // Student should be able to see an add submission button.
1515 $this->setUser($this->students[0]);
1516 $output = $assign->view_student_summary($this->students[0], true);
1517 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1518
1519 // Add a submission.
1520 $now = time();
1521 $submission = $assign->get_user_submission($this->students[0]->id, true);
1522 $data = new stdClass();
1523 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1524 'text'=>'Submission text',
1525 'format'=>FORMAT_MOODLE);
1526 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1527 $plugin->save($submission, $data);
1528
1529 // And now submit it for marking.
1530 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1531 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1532
1533 // Verify the student cannot make changes to the submission.
1534 $output = $assign->view_student_summary($this->students[0], true);
1535 $this->assertEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1536
1537 // Mark the submission.
1538 $this->setUser($this->teachers[0]);
1539 $data = new stdClass();
1540 $data->grade = '50.0';
1541 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1542
1543 // Check the student can see the grade.
1544 $this->setUser($this->students[0]);
1545 $output = $assign->view_student_summary($this->students[0], true);
1546 $this->assertNotEquals(false, strpos($output, '50.0'));
1547
1548 // Allow the student another attempt.
1549 $this->teachers[0]->ignoresesskey = true;
1550 $this->setUser($this->teachers[0]);
1551 $result = $assign->testable_process_add_attempt($this->students[0]->id);
1552 $this->assertEquals(true, $result);
1553
1554 // Check that the previous attempt is now in the submission history table.
1555 $this->setUser($this->students[0]);
1556 $output = $assign->view_student_summary($this->students[0], true);
1557 // Need a better check.
1558 $this->assertNotEquals(false, strpos($output, 'Submission text'), 'Contains: Submission text');
1559
1560 // Check that the student now has a button for Add a new attempt".
1561 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1562 // Check that the student now does not have a button for Submit.
1563 $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign')));
1564
1565 // Check that the student now has a submission history.
1566 $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign')));
1567
1568 $this->setUser($this->teachers[0]);
1569 // Check that the grading table loads correctly and contains this user.
1570 // This is also testing that we do not get duplicate rows in the grading table.
1571 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1572 $output = $assign->get_renderer()->render($gradingtable);
1573 $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
1574
1575 // Should be 1 not 2.
1576 $this->assertEquals(1, $assign->count_submissions());
1577 $this->assertEquals(1, $assign->count_submissions_with_status('reopened'));
1578 $this->assertEquals(0, $assign->count_submissions_need_grading());
1579 $this->assertEquals(1, $assign->count_grades());
1580
1581 // Change max attempts to unlimited.
1582 $formdata = clone($assign->get_instance());
1583 $formdata->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
1584 $formdata->instance = $formdata->id;
1585 $assign->update_instance($formdata);
1586
9e3eee67
DW
1587 // Mark the submission again.
1588 $data = new stdClass();
1589 $data->grade = '60.0';
1590 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1);
1591
1592 // Check the grade exists.
1593 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1594 $this->assertEquals(60, (int)$grades[$this->students[0]->id]->rawgrade);
1595
1596 // Check we can reopen still.
df211804
DW
1597 $result = $assign->testable_process_add_attempt($this->students[0]->id);
1598 $this->assertEquals(true, $result);
1599
9e3eee67 1600 // Should no longer have a grade because there is no grade for the latest attempt.
df211804 1601 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
9e3eee67 1602 $this->assertEmpty($grades);
df211804 1603
df211804 1604 }
46692c3a 1605
e77bacab
MP
1606 /**
1607 * Test reopen behavior when in "Reopen until pass" mode.
1608 */
1609 public function test_attempt_reopen_method_untilpass() {
1610 global $PAGE;
1611
1612 $this->setUser($this->editingteachers[0]);
1613 $assign = $this->create_instance(array('attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS,
1614 'maxattempts' => 3,
1615 'submissiondrafts' => 1,
1616 'assignsubmission_onlinetext_enabled' => 1));
1617 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1618
1619 // Set grade to pass to 80.
1620 $gradeitem = $assign->get_grade_item();
1621 $gradeitem->gradepass = '80.0';
1622 $gradeitem->update();
1623
1624 // Student should be able to see an add submission button.
1625 $this->setUser($this->students[0]);
1626 $output = $assign->view_student_summary($this->students[0], true);
1627 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1628
1629 // Add a submission.
1630 $now = time();
1631 $submission = $assign->get_user_submission($this->students[0]->id, true);
1632 $data = new stdClass();
1633 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1634 'text' => 'Submission text',
1635 'format' => FORMAT_MOODLE);
1636 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1637 $plugin->save($submission, $data);
1638
1639 // And now submit it for marking.
1640 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1641 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1642
1643 // Verify the student cannot make a new attempt.
1644 $output = $assign->view_student_summary($this->students[0], true);
1645 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1646
1647 // Mark the submission as non-passing.
1648 $this->setUser($this->teachers[0]);
1649 $data = new stdClass();
1650 $data->grade = '50.0';
1651 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1652
1653 // Check the student can see the grade.
1654 $this->setUser($this->students[0]);
1655 $output = $assign->view_student_summary($this->students[0], true);
1656 $this->assertNotEquals(false, strpos($output, '50.0'));
1657
1658 // Check that the student now has a button for Add a new attempt.
1659 $output = $assign->view_student_summary($this->students[0], true);
1660 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1661
1662 // Check that the student now does not have a button for Submit.
1663 $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign')));
1664
1665 // Check that the student now has a submission history.
1666 $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign')));
1667
1668 // Add a second submission.
1669 $now = time();
1670 $submission = $assign->get_user_submission($this->students[0]->id, true, 1);
1671 $data = new stdClass();
1672 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1673 'text' => 'Submission text',
1674 'format' => FORMAT_MOODLE);
1675 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1676 $plugin->save($submission, $data);
1677
1678 // And now submit it for marking.
1679 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1680 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1681
1682 // Mark the submission as passing.
1683 $this->setUser($this->teachers[0]);
1684 $data = new stdClass();
1685 $data->grade = '80.0';
1686 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1);
1687
1688 // Check that the student does not have a button for Add a new attempt.
1689 $this->setUser($this->students[0]);
1690 $output = $assign->view_student_summary($this->students[0], true);
1691 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1692
1693 // Re-mark the submission as not passing.
1694 $this->setUser($this->teachers[0]);
1695 $data = new stdClass();
1696 $data->grade = '50.0';
1697 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1);
1698
1699 // Check that the student now has a button for Add a new attempt.
1700 $this->setUser($this->students[0]);
1701 $output = $assign->view_student_summary($this->students[0], true);
1702 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1703
1704 // Add a submission as a second student.
1705 $this->setUser($this->students[1]);
1706 $now = time();
1707 $submission = $assign->get_user_submission($this->students[1]->id, true);
1708 $data = new stdClass();
1709 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1710 'text' => 'Submission text',
1711 'format' => FORMAT_MOODLE);
1712 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1713 $plugin->save($submission, $data);
1714
1715 // And now submit it for marking.
1716 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1717 $assign->testable_update_submission($submission, $this->students[1]->id, true, false);
1718
1719 // Mark the submission as passing.
1720 $this->setUser($this->teachers[0]);
1721 $data = new stdClass();
1722 $data->grade = '100.0';
1723 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
1724
1725 // Check the student can see the grade.
1726 $this->setUser($this->students[1]);
1727 $output = $assign->view_student_summary($this->students[1], true);
1728 $this->assertNotEquals(false, strpos($output, '100.0'));
1729
1730 // Check that the student does not have a button for Add a new attempt.
1731 $output = $assign->view_student_summary($this->students[1], true);
1732 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1733
1734 // Set grade to pass to 0, so that no attempts should reopen.
1735 $gradeitem = $assign->get_grade_item();
1736 $gradeitem->gradepass = '0';
1737 $gradeitem->update();
1738
1739 // Add another submission.
1740 $this->setUser($this->students[2]);
1741 $now = time();
1742 $submission = $assign->get_user_submission($this->students[2]->id, true);
1743 $data = new stdClass();
1744 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1745 'text' => 'Submission text',
1746 'format' => FORMAT_MOODLE);
1747 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1748 $plugin->save($submission, $data);
1749
1750 // And now submit it for marking.
1751 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1752 $assign->testable_update_submission($submission, $this->students[2]->id, true, false);
1753
1754 // Mark the submission as graded.
1755 $this->setUser($this->teachers[0]);
1756 $data = new stdClass();
1757 $data->grade = '0.0';
1758 $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0);
1759
1760 // Check the student can see the grade.
1761 $this->setUser($this->students[2]);
1762 $output = $assign->view_student_summary($this->students[2], true);
1763 $this->assertNotEquals(false, strpos($output, '0.0'));
1764
1765 // Check that the student does not have a button for Add a new attempt.
1766 $output = $assign->view_student_summary($this->students[2], true);
1767 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1768 }
1769
1770
f8d107b3
DM
1771 public function test_markingworkflow() {
1772 global $PAGE;
1773
1774 $this->setUser($this->editingteachers[0]);
1775 $assign = $this->create_instance(array('markingworkflow'=>1));
1776 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1777
13e82f1c 1778 // Mark the submission and set to notmarked.
f8d107b3
DM
1779 $this->setUser($this->teachers[0]);
1780 $data = new stdClass();
1781 $data->grade = '50.0';
1782 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED;
1783 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1784
1785 // Check the student can't see the grade.
1786 $this->setUser($this->students[0]);
1787 $output = $assign->view_student_summary($this->students[0], true);
1788 $this->assertEquals(false, strpos($output, '50.0'));
1789
5047b0ea
TB
1790 // Make sure the grade isn't pushed to the gradebook.
1791 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1792 $this->assertEmpty($grades);
1793
13e82f1c 1794 // Mark the submission and set to inmarking.
f8d107b3
DM
1795 $this->setUser($this->teachers[0]);
1796 $data = new stdClass();
1797 $data->grade = '50.0';
1798 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INMARKING;
1799 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1800
1801 // Check the student can't see the grade.
1802 $this->setUser($this->students[0]);
1803 $output = $assign->view_student_summary($this->students[0], true);
1804 $this->assertEquals(false, strpos($output, '50.0'));
1805
5047b0ea
TB
1806 // Make sure the grade isn't pushed to the gradebook.
1807 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1808 $this->assertEmpty($grades);
1809
13e82f1c 1810 // Mark the submission and set to readyforreview.
f8d107b3
DM
1811 $this->setUser($this->teachers[0]);
1812 $data = new stdClass();
1813 $data->grade = '50.0';
1814 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW;
1815 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1816
1817 // Check the student can't see the grade.
1818 $this->setUser($this->students[0]);
1819 $output = $assign->view_student_summary($this->students[0], true);
1820 $this->assertEquals(false, strpos($output, '50.0'));
1821
5047b0ea
TB
1822 // Make sure the grade isn't pushed to the gradebook.
1823 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1824 $this->assertEmpty($grades);
1825
13e82f1c 1826 // Mark the submission and set to inreview.
f8d107b3
DM
1827 $this->setUser($this->teachers[0]);
1828 $data = new stdClass();
1829 $data->grade = '50.0';
1830 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW;
1831 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1832
1833 // Check the student can't see the grade.
1834 $this->setUser($this->students[0]);
1835 $output = $assign->view_student_summary($this->students[0], true);
1836 $this->assertEquals(false, strpos($output, '50.0'));
1837
5047b0ea
TB
1838 // Make sure the grade isn't pushed to the gradebook.
1839 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1840 $this->assertEmpty($grades);
1841
13e82f1c 1842 // Mark the submission and set to readyforrelease.
f8d107b3
DM
1843 $this->setUser($this->teachers[0]);
1844 $data = new stdClass();
1845 $data->grade = '50.0';
1846 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE;
1847 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1848
1849 // Check the student can't see the grade.
1850 $this->setUser($this->students[0]);
1851 $output = $assign->view_student_summary($this->students[0], true);
1852 $this->assertEquals(false, strpos($output, '50.0'));
1853
5047b0ea
TB
1854 // Make sure the grade isn't pushed to the gradebook.
1855 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1856 $this->assertEmpty($grades);
1857
13e82f1c 1858 // Mark the submission and set to released.
f8d107b3
DM
1859 $this->setUser($this->teachers[0]);
1860 $data = new stdClass();
1861 $data->grade = '50.0';
1862 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED;
1863 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1864
1865 // Check the student can see the grade.
1866 $this->setUser($this->students[0]);
1867 $output = $assign->view_student_summary($this->students[0], true);
1868 $this->assertNotEquals(false, strpos($output, '50.0'));
5047b0ea
TB
1869
1870 // Make sure the grade is pushed to the gradebook.
1871 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1872 $this->assertEquals(50, (int)$grades[$this->students[0]->id]->rawgrade);
f8d107b3
DM
1873 }
1874
1875 public function test_markerallocation() {
1876 global $PAGE;
1877
1878 $this->setUser($this->editingteachers[0]);
13e82f1c 1879 $assign = $this->create_instance(array('markingworkflow'=>1, 'markingallocation'=>1));
f8d107b3
DM
1880 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1881
13e82f1c 1882 // Allocate marker to submission.
f8d107b3
DM
1883 $data = new stdClass();
1884 $data->allocatedmarker = $this->teachers[0]->id;
1885 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1886
13e82f1c 1887 // Check the allocated marker can view the submission.
f8d107b3
DM
1888 $this->setUser($this->teachers[0]);
1889 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1890 $output = $assign->get_renderer()->render($gradingtable);
1891 $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
1892
13e82f1c 1893 // Check that other teachers can't view this submission.
f8d107b3
DM
1894 $this->setUser($this->teachers[1]);
1895 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1896 $output = $assign->get_renderer()->render($gradingtable);
1897 $this->assertNotEquals(true, strpos($output, $this->students[0]->lastname));
1898 }
76e77b05 1899
3d1331be 1900
159b7f40 1901
57fbd5f9
DW
1902 public function test_teacher_submit_for_student() {
1903 global $PAGE;
1904
1905 $this->preventResetByRollback();
1906 $sink = $this->redirectMessages();
1907
1908 $this->setUser($this->editingteachers[0]);
1909
1910 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1));
1911 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1912
1913 $this->setUser($this->students[0]);
1914 // Simulate a submission.
1915 $data = new stdClass();
1916 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1917 'text'=>'Student submission text',
1918 'format'=>FORMAT_MOODLE);
1919
1920 $notices = array();
1921 $assign->save_submission($data, $notices);
1922
1923 // Check that the submission text was saved.
1924 $output = $assign->view_student_summary($this->students[0], true);
1925 $this->assertContains('Student submission text', $output, 'Contains student submission text');
1926
1927 // Check that a teacher teacher with the extra capability can edit a students submission.
1928 $this->setUser($this->teachers[0]);
1929 $data = new stdClass();
1930 $data->userid = $this->students[0]->id;
1931 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1932 'text'=>'Teacher edited submission text',
1933 'format'=>FORMAT_MOODLE);
1934
1935 // Add the required capability.
1936 $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
1937 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
1938 role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id);
1939 accesslib_clear_all_caches_for_unit_testing();
1940
1941 // Try to save the submission.
1942 $notices = array();
1943 $assign->save_submission($data, $notices);
1944
1945 // Check that the teacher can submit the students work.
1946 $data = new stdClass();
1947 $data->userid = $this->students[0]->id;
1948 $notices = array();
1949 $assign->submit_for_grading($data, $notices);
1950
1951 // Revert to draft so the student can edit it.
1952 $assign->revert_to_draft($this->students[0]->id);
1953
1954 $this->setUser($this->students[0]);
1955
1956 // Check that the submission text was saved.
1957 $output = $assign->view_student_summary($this->students[0], true);
1958 $this->assertContains('Teacher edited submission text', $output, 'Contains student submission text');
1959
1960 // Check that the student can submit their work.
1961 $data = new stdClass();
1962 $assign->submit_for_grading($data, $notices);
1963
1964 $output = $assign->view_student_summary($this->students[0], true);
1965 $this->assertNotContains(get_string('addsubmission', 'assign'), $output);
1966
1967 // Set to a default editing teacher who should not be able to edit this submission.
1968 $this->setUser($this->editingteachers[1]);
1969
1970 // Revert to draft so the submission is editable.
1971 $assign->revert_to_draft($this->students[0]->id);
1972
1973 $data = new stdClass();
1974 $data->userid = $this->students[0]->id;
1975 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1976 'text'=>'Teacher 2 edited submission text',
1977 'format'=>FORMAT_MOODLE);
1978
1979 $notices = array();
1980 $this->setExpectedException('moodle_exception');
1981 $assign->save_submission($data, $notices);
1982
1983 $sink->close();
1984 }
1985
9054c04d 1986 public function test_disable_submit_after_cutoff_date() {
1987 global $PAGE;
1988
1989 $this->setUser($this->editingteachers[0]);
1990 $now = time();
1991 $tomorrow = $now + 24*60*60;
1992 $lastweek = $now - 7*24*60*60;
1993 $yesterday = $now - 24*60*60;
1994
1995 $assign = $this->create_instance(array('duedate'=>$yesterday,
1996 'cutoffdate'=>$tomorrow,
1997 'assignsubmission_onlinetext_enabled'=>1));
1998 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1999
2000 // Student should be able to see an add submission button.
2001 $this->setUser($this->students[0]);
2002 $output = $assign->view_student_summary($this->students[0], true);
2003 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
2004
2005 // Add a submission but don't submit now.
2006 $submission = $assign->get_user_submission($this->students[0]->id, true);
2007 $data = new stdClass();
2008 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
2009 'text'=>'Submission text',
2010 'format'=>FORMAT_MOODLE);
2011 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
2012 $plugin->save($submission, $data);
2013
2014 // Create another instance with cut-off and due-date already passed.
2015 $this->setUser($this->editingteachers[0]);
2016 $now = time();
2017 $assign = $this->create_instance(array('duedate'=>$lastweek,
2018 'cutoffdate'=>$yesterday,
2019 'assignsubmission_onlinetext_enabled'=>1));
2020
2021 $this->setUser($this->students[0]);
2022 $output = $assign->view_student_summary($this->students[0], true);
2023 $this->assertNotContains($output, get_string('editsubmission', 'assign'),
2024 'Should not be able to edit after cutoff date.');
2025 $this->assertNotContains($output, get_string('submitassignment', 'assign'),
2026 'Should not be able to submit after cutoff date.');
2027 }
f159ad73 2028 /**
2029 * Testing for submission comment plugin settings
2030 */
2031 public function test_submission_comment_plugin_settings() {
2032 global $CFG;
2033
2034 $commentconfig = false;
2035 if (!empty($CFG->usecomments)) {
2036 $commentconfig = $CFG->usecomments;
2037 }
2038
2039 $CFG->usecomments = true;
2040 $assign = $this->create_instance();
2041 $plugin = $assign->get_submission_plugin_by_type('comments');
2042 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2043
2044 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0));
2045 $plugin = $assign->get_submission_plugin_by_type('comments');
2046 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2047
2048 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1));
2049 $plugin = $assign->get_submission_plugin_by_type('comments');
2050 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2051
2052 $CFG->usecomments = false;
2053 $assign = $this->create_instance();
2054 $plugin = $assign->get_submission_plugin_by_type('comments');
2055 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2056
2057 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0));
2058 $plugin = $assign->get_submission_plugin_by_type('comments');
2059 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2060
2061 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1));
2062 $plugin = $assign->get_submission_plugin_by_type('comments');
2063 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2064
2065 $CFG->usecomments = $commentconfig;
2066 }
2067
c7a73689
DW
2068 /**
2069 * Testing for comment inline settings
2070 */
2071 public function test_feedback_comment_commentinline() {
2072 global $CFG;
2073
2074 $sourcetext = "Hello!
2075
2076I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness.
2077
2078URL outside a tag: https://moodle.org/logo/logo-240x60.gif
2079Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif
2080
2081External link 1:<img src='https://moodle.org/logo/logo-240x60.gif' alt='Moodle'/>
2082External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\"/>
2083Internal link 1:<img src='@@PLUGINFILE@@/logo-240x60.gif' alt='Moodle'/>
2084Internal link 2:<img alt=\"Moodle\" src=\"@@PLUGINFILE@@logo-240x60.gif\"/>
2085Anchor link 1:<a href=\"@@PLUGINFILE@@logo-240x60.gif\" alt=\"bananas\">Link text</a>
2086Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
2087";
2088
2089 // Note the internal images have been stripped and the html is purified (quotes fixed in this case).
2090 $filteredtext = "Hello!
2091
2092I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness.
2093
2094URL outside a tag: https://moodle.org/logo/logo-240x60.gif
2095Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif
2096
2097External link 1:<img src=\"https://moodle.org/logo/logo-240x60.gif\" alt=\"Moodle\" />
2098External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\" />
2099Internal link 1:
2100Internal link 2:
2101Anchor link 1:Link text
2102Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
2103";
2104
2105 $this->setUser($this->editingteachers[0]);
2106 $params = array('assignsubmission_onlinetext_enabled' => 1,
2107 'assignfeedback_comments_enabled' => 1,
2108 'assignfeedback_comments_commentinline' => 1);
2109 $assign = $this->create_instance($params);
2110
2111 $this->setUser($this->students[0]);
2112 // Add a submission but don't submit now.
2113 $submission = $assign->get_user_submission($this->students[0]->id, true);
2114 $data = new stdClass();
2115
2116 // Test the internal link is stripped, but the external one is not.
2117 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
2118 'text'=>$sourcetext,
2119 'format'=>FORMAT_MOODLE);
2120
2121 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
2122 $plugin->save($submission, $data);
2123
2124 $this->setUser($this->editingteachers[0]);
2125
2126 $data = new stdClass();
2127 require_once($CFG->dirroot . '/mod/assign/gradeform.php');
2128 $pagination = array('userid'=>$this->students[0]->id,
2129 'rownum'=>0,
2130 'last'=>true,
2131 'useridlistid'=>time(),
2132 'attemptnumber'=>0);
2133 $formparams = array($assign, $data, $pagination);
2134 $mform = new mod_assign_grade_form(null, $formparams);
2135
2136 $this->assertEquals($filteredtext, $data->assignfeedbackcomments_editor['text']);
2137 }
2138
f159ad73 2139 /**
2140 * Testing for feedback comment plugin settings
2141 */
2142 public function test_feedback_plugin_settings() {
2143
2144 $assign = $this->create_instance();
2145 $plugin = $assign->get_feedback_plugin_by_type('comments');
2146 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2147
2148 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 0));
2149 $plugin = $assign->get_feedback_plugin_by_type('comments');
2150 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2151
2152 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
2153 $plugin = $assign->get_feedback_plugin_by_type('comments');
2154 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2155 }
456d7bc7
RT
2156
2157 /**
2158 * Testing if gradebook feedback plugin is enabled.
2159 */
2160 public function test_is_gradebook_feedback_enabled() {
2161 $adminconfig = get_config('assign');
2162 $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;
2163
2164 // Create assignment with gradebook feedback enabled and grade = 0.
2165 $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 1, 'grades' => 0));
2166
2167 // Get gradebook feedback plugin.
2168 $gradebookplugintype = str_replace('assignfeedback_', '', $gradebookplugin);
2169 $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype);
2170 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2171 $this->assertEquals(1, $assign->is_gradebook_feedback_enabled());
2172
2173 // Create assignment with gradebook feedback disabled and grade = 0.
2174 $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 0, 'grades' => 0));
2175 $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype);
2176 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2177 }
57fbd5f9
DW
2178
2179 /**
2180 * Testing can_edit_submission
2181 */
2182 public function test_can_edit_submission() {
2183 global $PAGE, $DB;
2184 $this->create_extra_users();
2185
2186 $this->setAdminUser();
2187 // Create assignment (onlinetext).
2188 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1));
2189 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
2190
2191 // Check student can edit their own submission.
2192 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->students[0]->id));
2193 // Check student cannot edit others submission.
2194 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->students[1]->id));
2195
2196 // Check teacher cannot (by default) edit a students submission.
2197 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id));
2198
2199 // Add the required capability to edit a student submission.
2200 $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
2201 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
2202 role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id);
2203 accesslib_clear_all_caches_for_unit_testing();
2204 // Retest - should now have access.
2205 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id));
2206
2207 // Force create an assignment with SEPARATEGROUPS.
2208 $data = new stdClass();
2209 $data->courseid = $this->course->id;
2210 $data->name = 'Grouping';
2211 $groupingid = groups_create_grouping($data);
2212 groups_assign_grouping($groupingid, $this->groups[0]->id);
2213 groups_assign_grouping($groupingid, $this->groups[1]->id);
2214 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
2215
2216 // Add the capability to the new assignment for extra students 0 and 1.
2217 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
2218 role_assign($roleid, $this->extrastudents[0]->id, $assign->get_context()->id);
2219 role_assign($roleid, $this->extrastudents[1]->id, $assign->get_context()->id);
2220 accesslib_clear_all_caches_for_unit_testing();
2221
2222 // Verify the extra student does not have the capability to edit a submission not in their group.
2223 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[1]->id));
2224 // Verify the extra student does have the capability to edit a submission in their group.
2225 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[0]->id));
2226
2227 }
323f221b
MH
2228
2229 /**
2230 * Test if the view blind details capability works
2231 */
2232 public function test_can_view_blind_details() {
2233 global $PAGE, $DB;
2234 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2235 $managerrole = $DB->get_record('role', array('shortname' => 'manager'));
2236
2237 $student = $this->students[0];// Get a student user.
2238 // Create a teacher. Shouldn't be able to view blind marking ID.
2239 $teacher = $this->getDataGenerator()->create_user();
2240
2241 $this->getDataGenerator()->enrol_user($teacher->id,
2242 $this->course->id,
2243 $teacherrole->id);
2244
2245 // Create a manager.. Should be able to view blind marking ID.
2246 $manager = $this->getDataGenerator()->create_user();
e28d6b29
MG
2247 $this->getDataGenerator()->enrol_user($manager->id,
2248 $this->course->id,
323f221b
MH
2249 $managerrole->id);
2250
2251 // Generate blind marking assignment.
e28d6b29 2252 $assign = $this->create_instance(array('blindmarking' => 1));
323f221b
MH
2253 $this->assertEquals(true, $assign->is_blind_marking());
2254
2255 // Test student names are hidden to teacher.
e28d6b29
MG
2256 $this->setUser($teacher);
2257 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
2258 $output = $assign->get_renderer()->render($gradingtable);
323f221b
MH
2259 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign'))); // "Participant" is somewhere on the page.
2260 $this->assertEquals(false, strpos($output, fullname($student))); // Students full name doesn't appear.
2261
2262 // Test student names are visible to manager.
e28d6b29
MG
2263 $this->setUser($manager);
2264 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
2265 $output = $assign->get_renderer()->render($gradingtable);
8c674e80 2266 $this->assertEquals(false, strpos($output, get_string('hiddenuser', 'assign')));
323f221b
MH
2267 $this->assertEquals(true, strpos($output, fullname($student))); //students full name doesn't appear.
2268 }
47f48152
DW
2269}
2270