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