MDL-40055 mod_assign: Replace add_to_log 'reveal identities'
[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;
86 $this->setUser($this->students[0]);
87 $this->setExpectedException('required_capability_exception');
88 $assign->testable_process_reveal_identities();
89
90 // Test teachers cannot reveal identities.
91 $nopermission = false;
92 $this->setUser($this->teachers[0]);
93 $this->setExpectedException('required_capability_exception');
94 $assign->testable_process_reveal_identities();
95
96 // Test sesskey is required.
47f48152
DW
97 $this->setUser($this->editingteachers[0]);
98 $this->setExpectedException('moodle_exception');
99 $assign->testable_process_reveal_identities();
100
101 // Test editingteacher can reveal identities if sesskey is ignored.
102 $this->editingteachers[0]->ignoresesskey = true;
103 $this->setUser($this->editingteachers[0]);
104 $assign->testable_process_reveal_identities();
105 $this->assertEquals(false, $assign->is_blind_marking());
106
107 // Test student names are visible.
108 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
109 $output = $assign->get_renderer()->render($gradingtable);
110 $this->assertEquals(false, strpos($output, get_string('hiddenuser', 'assign')));
111
112 // Set this back to default.
113 $this->editingteachers[0]->ignoresesskey = false;
114 }
115
116 public function test_show_intro() {
117 // Test whether we are showing the intro at the correct times.
118 $this->setUser($this->editingteachers[0]);
119 $assign = $this->create_instance(array('alwaysshowdescription'=>1));
120
121 $this->assertEquals(true, $assign->testable_show_intro());
122
123 $tomorrow = time() + (24*60*60);
124
125 $assign = $this->create_instance(array('alwaysshowdescription'=>0,
126 'allowsubmissionsfromdate'=>$tomorrow));
127 $this->assertEquals(false, $assign->testable_show_intro());
128 $yesterday = time() - (24*60*60);
129 $assign = $this->create_instance(array('alwaysshowdescription'=>0,
130 'allowsubmissionsfromdate'=>$yesterday));
131 $this->assertEquals(true, $assign->testable_show_intro());
132 }
133
134 public function test_has_submissions_or_grades() {
135 $this->setUser($this->editingteachers[0]);
136 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
137
138 $instance = $assign->get_instance();
139
140 // Should start empty.
141 $this->assertEquals(false, $assign->has_submissions_or_grades());
142
143 // Simulate a submission.
144 $this->setUser($this->students[0]);
145 $submission = $assign->get_user_submission($this->students[0]->id, true);
146 $data = new stdClass();
147 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
148 'text'=>'Submission text',
149 'format'=>FORMAT_MOODLE);
150 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
151 $plugin->save($submission, $data);
152
153 // Now test again.
154 $this->assertEquals(true, $assign->has_submissions_or_grades());
155 // Set this back to default.
156 $this->students[0]->ignoresesskey = false;
157 }
158
159 public function test_delete_grades() {
160 $this->setUser($this->editingteachers[0]);
161 $assign = $this->create_instance();
162
163 // Simulate adding a grade.
164 $this->setUser($this->teachers[0]);
165 $data = new stdClass();
166 $data->grade = '50.0';
df211804 167 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
168
169 // Now see if the data is in the gradebook.
170 $gradinginfo = grade_get_grades($this->course->id,
171 'mod',
172 'assign',
173 $assign->get_instance()->id);
174
175 $this->assertNotEquals(0, count($gradinginfo->items));
176
177 $assign->testable_delete_grades();
178 $gradinginfo = grade_get_grades($this->course->id,
179 'mod',
180 'assign',
181 $assign->get_instance()->id);
182
183 $this->assertEquals(0, count($gradinginfo->items));
184 }
185
186 public function test_delete_instance() {
187 $this->setUser($this->editingteachers[0]);
188 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
189
190 // Simulate adding a grade.
191 $this->setUser($this->teachers[0]);
192 $data = new stdClass();
193 $data->grade = '50.0';
df211804 194 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
195
196 // Simulate a submission.
197 $this->setUser($this->students[0]);
198 $submission = $assign->get_user_submission($this->students[0]->id, true);
199 $data = new stdClass();
200 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
201 'text'=>'Submission text',
202 'format'=>FORMAT_MOODLE);
203 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
204 $plugin->save($submission, $data);
205
206 // Now try and delete.
207 $this->assertEquals(true, $assign->delete_instance());
208 }
209
210 public function test_reset_userdata() {
211 global $DB;
212
213 $now = time();
214 $this->setUser($this->editingteachers[0]);
215 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1,
216 'duedate'=>$now));
217
218 // Simulate adding a grade.
219 $this->setUser($this->teachers[0]);
220 $data = new stdClass();
221 $data->grade = '50.0';
df211804 222 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
223
224 // Simulate a submission.
225 $this->setUser($this->students[0]);
226 $submission = $assign->get_user_submission($this->students[0]->id, true);
227 $data = new stdClass();
228 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
229 'text'=>'Submission text',
230 'format'=>FORMAT_MOODLE);
231 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
232 $plugin->save($submission, $data);
233
234 $this->assertEquals(true, $assign->has_submissions_or_grades());
235 // Now try and reset.
236 $data = new stdClass();
237 $data->reset_assign_submissions = 1;
238 $data->reset_gradebook_grades = 1;
239 $data->courseid = $this->course->id;
240 $data->timeshift = 24*60*60;
241 $this->setUser($this->editingteachers[0]);
242 $assign->reset_userdata($data);
243 $this->assertEquals(false, $assign->has_submissions_or_grades());
244
245 // Reload the instance data.
246 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
247 $this->assertEquals($now + 24*60*60, $instance->duedate);
248 }
249
250 public function test_plugin_settings() {
251 global $DB;
252
253 $now = time();
254 $this->setUser($this->editingteachers[0]);
255 $assign = $this->create_instance(array('assignsubmission_file_enabled'=>1,
256 'assignsubmission_file_maxfiles'=>12,
257 'assignsubmission_file_maxsizebytes'=>10));
258
259 $plugin = $assign->get_submission_plugin_by_type('file');
260 $this->assertEquals('12', $plugin->get_config('maxfilesubmissions'));
261 }
262
263 public function test_update_calendar() {
264 global $DB;
265
266 $now = time();
267 $this->setUser($this->editingteachers[0]);
268 $assign = $this->create_instance(array('duedate'=>$now));
269
270 // See if there is an event in the calendar.
271 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
272 $id = $DB->get_field('event', 'id', $params);
273
274 $this->assertEquals(false, empty($id));
275 }
276
277 public function test_update_instance() {
278 global $DB;
279
280 $this->setUser($this->editingteachers[0]);
281 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
282
283 $now = time();
284 $instance = $assign->get_instance();
285 $instance->duedate = $now;
286 $instance->instance = $instance->id;
287 $instance->assignsubmission_onlinetext_enabled = 1;
47f48152
DW
288
289 $assign->update_instance($instance);
290
291 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
292 $this->assertEquals($now, $instance->duedate);
293 }
294
295 public function test_list_participants() {
df211804 296 $this->create_extra_users();
47f48152
DW
297 $this->setUser($this->editingteachers[0]);
298 $assign = $this->create_instance(array('grade'=>100));
299
a5c793c3 300 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
e6cc5347
RT
301
302 // Teacher with user preference set should see suspended users as well.
303 set_user_preference('grade_report_showonlyactiveenrol', false);
304 $assign = $this->create_instance(array('grade'=>100));
305 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT,
306 count($assign->list_participants(null, true)));
307
1ecb8044 308 // Non-editing teacher should not see suspended users, even if user preference is set.
e6cc5347
RT
309 $this->setUser($this->teachers[0]);
310 set_user_preference('grade_report_showonlyactiveenrol', false);
311 $assign = $this->create_instance(array('grade'=>100));
312 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
47f48152
DW
313 }
314
315 public function test_count_teams() {
df211804 316 $this->create_extra_users();
47f48152
DW
317 $this->setUser($this->editingteachers[0]);
318 $assign = $this->create_instance(array('teamsubmission'=>1));
319
a5c793c3 320 $this->assertEquals(self::GROUP_COUNT + 1, $assign->count_teams());
47f48152
DW
321 }
322
323 public function test_count_submissions() {
df211804 324 $this->create_extra_users();
47f48152
DW
325 $this->setUser($this->editingteachers[0]);
326 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
327
328 // Simulate a submission.
a5c793c3
DW
329 $this->setUser($this->extrastudents[0]);
330 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
47f48152
DW
331 // Leave this one as DRAFT.
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 // Simulate adding a grade.
340 $this->setUser($this->teachers[0]);
341 $data = new stdClass();
342 $data->grade = '50.0';
df211804 343 $assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0);
47f48152
DW
344
345 // Simulate a submission.
a5c793c3
DW
346 $this->setUser($this->extrastudents[1]);
347 $submission = $assign->get_user_submission($this->extrastudents[1]->id, true);
47f48152 348 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
a5c793c3 349 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
47f48152
DW
350 $data = new stdClass();
351 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
352 'text'=>'Submission text',
353 'format'=>FORMAT_MOODLE);
354 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
355 $plugin->save($submission, $data);
356
357 // Simulate a submission.
a5c793c3
DW
358 $this->setUser($this->extrastudents[2]);
359 $submission = $assign->get_user_submission($this->extrastudents[2]->id, true);
47f48152 360 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
a5c793c3 361 $assign->testable_update_submission($submission, $this->extrastudents[2]->id, true, false);
47f48152
DW
362 $data = new stdClass();
363 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
364 'text'=>'Submission text',
365 'format'=>FORMAT_MOODLE);
366 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
367 $plugin->save($submission, $data);
368
369 // Simulate a submission.
a5c793c3
DW
370 $this->setUser($this->extrastudents[3]);
371 $submission = $assign->get_user_submission($this->extrastudents[3]->id, true);
47f48152 372 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
a5c793c3 373 $assign->testable_update_submission($submission, $this->extrastudents[3]->id, true, false);
47f48152
DW
374 $data = new stdClass();
375 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
376 'text'=>'Submission text',
377 'format'=>FORMAT_MOODLE);
378 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
379 $plugin->save($submission, $data);
380
e6cc5347
RT
381 // Simulate a submission for suspended user, this will never be counted.
382 $this->setUser($this->extrastudents[3]);
383 $submission = $assign->get_user_submission($this->extrasuspendedstudents[0]->id, true);
384 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
385 $assign->testable_update_submission($submission, $this->extrasuspendedstudents[0]->id, true, false);
386 $data = new stdClass();
387 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
388 'text'=>'Submission text',
389 'format'=>FORMAT_MOODLE);
390 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
391 $plugin->save($submission, $data);
392
47f48152
DW
393 // Simulate adding a grade.
394 $this->setUser($this->teachers[0]);
395 $data = new stdClass();
396 $data->grade = '50.0';
df211804 397 $assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0);
e6cc5347 398 $assign->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0);
47f48152
DW
399
400 $this->assertEquals(2, $assign->count_grades());
401 $this->assertEquals(4, $assign->count_submissions());
402 $this->assertEquals(2, $assign->count_submissions_need_grading());
403 $this->assertEquals(3, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
404 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
405 }
406
407 public function test_get_grading_userid_list() {
df211804 408 $this->create_extra_users();
47f48152
DW
409 $this->setUser($this->editingteachers[0]);
410 $assign = $this->create_instance();
411
412 $users = $assign->testable_get_grading_userid_list();
a5c793c3 413 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($users));
e6cc5347
RT
414
415 $this->setUser($this->editingteachers[0]);
416 set_user_preference('grade_report_showonlyactiveenrol', false);
417 $assign = $this->create_instance();
418
419 $users = $assign->testable_get_grading_userid_list();
420 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT, count($users));
47f48152
DW
421 }
422
423 public function test_cron() {
424 // First run cron so there are no messages waiting to be sent (from other tests).
425 cron_setup_user();
426 assign::cron();
427
428 // Now create an assignment and add some feedback.
429 $this->setUser($this->editingteachers[0]);
430 $assign = $this->create_instance();
431
432 // Simulate adding a grade.
433 $this->setUser($this->teachers[0]);
434 $data = new stdClass();
435 $data->grade = '50.0';
df211804 436 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
437
438 // Now run cron and see that one message was sent.
439 $this->preventResetByRollback();
440 $sink = $this->redirectMessages();
441 cron_setup_user();
442 $this->expectOutputRegex('/Done processing 1 assignment submissions/');
443 assign::cron();
444
445 $messages = $sink->get_messages();
446 $this->assertEquals(1, count($messages));
447 $this->assertEquals(1, $messages[0]->notification);
448 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
449 }
450
451 public function test_is_graded() {
452 $this->setUser($this->editingteachers[0]);
453 $assign = $this->create_instance();
454
455 // Simulate adding a grade.
456 $this->setUser($this->teachers[0]);
457 $data = new stdClass();
458 $data->grade = '50.0';
df211804 459 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
460
461 $this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id));
462 $this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
463 }
464
465 public function test_can_view_submission() {
e6cc5347 466 $this->create_extra_users();
47f48152
DW
467 $this->setUser($this->editingteachers[0]);
468 $assign = $this->create_instance();
469
470 $this->setUser($this->students[0]);
471 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
472 $this->assertEquals(false, $assign->can_view_submission($this->students[1]->id));
473 $this->assertEquals(false, $assign->can_view_submission($this->teachers[0]->id));
474 $this->setUser($this->teachers[0]);
475 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
476 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
477 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
e6cc5347 478 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
47f48152
DW
479 $this->setUser($this->editingteachers[0]);
480 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
481 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
482 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
e6cc5347 483 $this->assertEquals(true, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
47f48152
DW
484 }
485
486
487 public function test_update_submission() {
df211804 488 $this->create_extra_users();
47f48152
DW
489 $this->setUser($this->editingteachers[0]);
490 $assign = $this->create_instance();
491
a5c793c3 492 $this->setUser($this->extrastudents[0]);
47f48152 493 $now = time();
a5c793c3
DW
494 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
495 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
496
497 $this->setUser($this->teachers[0]);
498 // Verify the gradebook update.
499 $gradinginfo = grade_get_grades($this->course->id,
500 'mod',
501 'assign',
502 $assign->get_instance()->id,
a5c793c3 503 $this->extrastudents[0]->id);
47f48152 504
a5c793c3
DW
505 $this->assertEquals($this->extrastudents[0]->id,
506 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
47f48152
DW
507
508 // Now verify group assignments.
509 $this->setUser($this->editingteachers[0]);
510 $assign = $this->create_instance(array('teamsubmission'=>1));
511
a5c793c3 512 $this->setUser($this->extrastudents[0]);
47f48152 513 $now = time();
a5c793c3
DW
514 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
515 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
47f48152 516
e6cc5347 517 // Check that at least 2 active members and 1 suspended member of the submission group had their submission updated.
47f48152
DW
518
519 $this->setUser($this->editingteachers[0]);
520 $gradinginfo = grade_get_grades($this->course->id,
521 'mod',
522 'assign',
523 $assign->get_instance()->id,
a5c793c3 524 $this->extrastudents[0]->id);
47f48152 525
a5c793c3
DW
526 $this->assertEquals($this->extrastudents[0]->id,
527 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
47f48152
DW
528
529 $gradinginfo = grade_get_grades($this->course->id,
530 'mod',
531 'assign',
532 $assign->get_instance()->id,
a5c793c3 533 $this->extrastudents[self::GROUP_COUNT]->id);
47f48152 534
a5c793c3
DW
535 $this->assertEquals($this->extrastudents[self::GROUP_COUNT]->id,
536 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT]->id]->usermodified);
47f48152 537
e6cc5347
RT
538 $gradinginfo = grade_get_grades($this->course->id,
539 'mod',
540 'assign',
541 $assign->get_instance()->id,
542 $this->extrasuspendedstudents[0]->id);
543 $this->assertEquals($this->extrasuspendedstudents[0]->id,
544 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[0]->id]->usermodified);
545
546 // Check the same with non-editing teacher and make sure submission is not updated for suspended user.
547 $this->setUser($this->editingteachers[0]);
548 $assign = $this->create_instance(array('teamsubmission'=>1));
549
550 $this->setUser($this->extrastudents[1]);
551 $now = time();
552 $submission = $assign->get_group_submission($this->extrastudents[1]->id, 0, true);
553 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, true);
554
555 $this->setUser($this->teachers[0]);
556 $gradinginfo = grade_get_grades($this->course->id,
557 'mod',
558 'assign',
559 $assign->get_instance()->id,
560 $this->extrastudents[1]->id);
561
562 $this->assertEquals($this->extrastudents[1]->id,
563 $gradinginfo->items[0]->grades[$this->extrastudents[1]->id]->usermodified);
564
565 $gradinginfo = grade_get_grades($this->course->id,
566 'mod',
567 'assign',
568 $assign->get_instance()->id,
569 $this->extrastudents[self::GROUP_COUNT+1]->id);
570
571 $this->assertEquals($this->extrastudents[self::GROUP_COUNT+1]->id,
572 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT+1]->id]->usermodified);
573
574 $gradinginfo = grade_get_grades($this->course->id,
575 'mod',
576 'assign',
577 $assign->get_instance()->id,
578 $this->extrasuspendedstudents[1]->id);
579 $this->assertEquals($this->extrasuspendedstudents[1]->id,
580 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[1]->id]->usermodified);
581
47f48152
DW
582 // Now verify blind marking.
583 $this->setUser($this->editingteachers[0]);
584 $assign = $this->create_instance(array('blindmarking'=>1));
585
a5c793c3 586 $this->setUser($this->extrastudents[0]);
47f48152 587 $now = time();
a5c793c3
DW
588 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
589 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
590
591 $this->setUser($this->editingteachers[0]);
592 $gradinginfo = grade_get_grades($this->course->id,
593 'mod',
594 'assign',
595 $assign->get_instance()->id,
a5c793c3 596 $this->extrastudents[0]->id);
47f48152 597
a5c793c3 598 $this->assertEquals(null, $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->datesubmitted);
47f48152
DW
599 }
600
601 public function test_submissions_open() {
602 $this->setUser($this->editingteachers[0]);
603
604 $now = time();
605 $tomorrow = $now + 24*60*60;
606 $oneweek = $now + 7*24*60*60;
607 $yesterday = $now - 24*60*60;
608
609 $assign = $this->create_instance();
610 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
611
612 $assign = $this->create_instance(array('duedate'=>$tomorrow));
613 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
614
615 $assign = $this->create_instance(array('duedate'=>$yesterday));
616 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
617
618 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$tomorrow));
619 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
620
621 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$yesterday));
622 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
623
624 $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
625 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
626
627 $assign = $this->create_instance(array('submissiondrafts'=>1));
628 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
629
630 $this->setUser($this->students[0]);
631 $now = time();
632 $submission = $assign->get_user_submission($this->students[0]->id, true);
633 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
634 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
635 $this->setUser($this->editingteachers[0]);
636 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
637 }
638
639 public function test_get_graders() {
df211804 640 $this->create_extra_users();
47f48152
DW
641 $this->setUser($this->editingteachers[0]);
642 $assign = $this->create_instance();
643
a5c793c3
DW
644 $this->assertCount(self::DEFAULT_TEACHER_COUNT +
645 self::DEFAULT_EDITING_TEACHER_COUNT +
646 self::EXTRA_TEACHER_COUNT +
647 self::EXTRA_EDITING_TEACHER_COUNT,
648 $assign->testable_get_graders($this->students[0]->id));
47f48152
DW
649
650 $assign = $this->create_instance();
651 // Force create an assignment with SEPARATEGROUPS.
652 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
653 $params = array('course'=>$this->course->id);
654 $instance = $generator->create_instance($params);
655 $cm = get_coursemodule_from_instance('assign', $instance->id);
656 set_coursemodule_groupmode($cm->id, SEPARATEGROUPS);
657 $cm->groupmode = SEPARATEGROUPS;
658 $context = context_module::instance($cm->id);
659 $assign = new testable_assign($context, $cm, $this->course);
660
661 $this->setUser($this->students[1]);
a5c793c3 662 $this->assertCount(4, $assign->testable_get_graders($this->students[0]->id));
47f48152
DW
663 }
664
665 public function test_get_uniqueid_for_user() {
666 $this->setUser($this->editingteachers[0]);
667 $assign = $this->create_instance();
668
669 foreach ($this->students as $student) {
670 $uniqueid = $assign->get_uniqueid_for_user($student->id);
671 $this->assertEquals($student->id, $assign->get_user_id_for_uniqueid($uniqueid));
672 }
673 }
674
46692c3a 675 public function test_show_student_summary() {
c2114099 676 global $CFG, $PAGE;
46692c3a
DW
677
678 $this->setUser($this->editingteachers[0]);
679 $assign = $this->create_instance();
c2114099 680 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
46692c3a
DW
681
682 // No feedback should be available because this student has not been graded.
683 $this->setUser($this->students[0]);
684 $output = $assign->view_student_summary($this->students[0], true);
685 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if there is no grade');
686 // Simulate adding a grade.
687 $this->setUser($this->teachers[0]);
688 $data = new stdClass();
689 $data->grade = '50.0';
df211804 690 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
46692c3a 691
b0da618b 692 // Now we should see the feedback.
46692c3a
DW
693 $this->setUser($this->students[0]);
694 $output = $assign->view_student_summary($this->students[0], true);
695 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback if there is a grade');
696
697 // Now hide the grade in gradebook.
698 $this->setUser($this->teachers[0]);
699 require_once($CFG->libdir.'/gradelib.php');
700 $gradeitem = new grade_item(array(
701 'itemtype' => 'mod',
702 'itemmodule' => 'assign',
703 'iteminstance' => $assign->get_instance()->id,
704 'courseid' => $this->course->id));
705
706 $gradeitem->set_hidden(1, false);
707
708 // No feedback should be available because the grade is hidden.
709 $this->setUser($this->students[0]);
710 $output = $assign->view_student_summary($this->students[0], true);
711 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
712
b0da618b 713 // Do the same but add feedback.
46692c3a
DW
714 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
715
716 $this->setUser($this->teachers[0]);
717 $grade = $assign->get_user_grade($this->students[0]->id, true);
718 $data = new stdClass();
719 $data->assignfeedbackcomments_editor = array('text'=>'Tomato sauce',
720 'format'=>FORMAT_MOODLE);
721 $plugin = $assign->get_feedback_plugin_by_type('comments');
722 $plugin->save($grade, $data);
723
b0da618b 724 // Should have feedback but no grade.
46692c3a
DW
725 $this->setUser($this->students[0]);
726 $output = $assign->view_student_summary($this->students[0], true);
ea698284 727 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback even if there is no grade');
46692c3a
DW
728 $this->assertEquals(false, strpos($output, 'Grade'), 'Do not show grade when there is no grade.');
729 $this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.');
45aac51a 730
ea698284
AD
731 // Now hide the grade in gradebook.
732 $this->setUser($this->teachers[0]);
733 $gradeitem = new grade_item(array(
734 'itemtype' => 'mod',
735 'itemmodule' => 'assign',
736 'iteminstance' => $assign->get_instance()->id,
737 'courseid' => $this->course->id));
738
739 $gradeitem->set_hidden(1, false);
740
741 // No feedback should be available because the grade is hidden.
742 $this->setUser($this->students[0]);
743 $output = $assign->view_student_summary($this->students[0], true);
744 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
46692c3a
DW
745 }
746
df211804
DW
747 public function test_attempt_reopen_method_manual() {
748 global $PAGE;
749
750 $this->setUser($this->editingteachers[0]);
751 $assign = $this->create_instance(array('attemptreopenmethod'=>ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
752 'maxattempts'=>3,
753 'submissiondrafts'=>1,
754 'assignsubmission_onlinetext_enabled'=>1));
755 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
756
757 // Student should be able to see an add submission button.
758 $this->setUser($this->students[0]);
759 $output = $assign->view_student_summary($this->students[0], true);
760 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
761
762 // Add a submission.
763 $now = time();
764 $submission = $assign->get_user_submission($this->students[0]->id, true);
765 $data = new stdClass();
766 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
767 'text'=>'Submission text',
768 'format'=>FORMAT_MOODLE);
769 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
770 $plugin->save($submission, $data);
771
772 // And now submit it for marking.
773 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
774 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
775
776 // Verify the student cannot make changes to the submission.
777 $output = $assign->view_student_summary($this->students[0], true);
778 $this->assertEquals(false, strpos($output, get_string('addsubmission', 'assign')));
779
780 // Mark the submission.
781 $this->setUser($this->teachers[0]);
782 $data = new stdClass();
783 $data->grade = '50.0';
784 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
785
786 // Check the student can see the grade.
787 $this->setUser($this->students[0]);
788 $output = $assign->view_student_summary($this->students[0], true);
789 $this->assertNotEquals(false, strpos($output, '50.0'));
790
791 // Allow the student another attempt.
792 $this->teachers[0]->ignoresesskey = true;
793 $this->setUser($this->teachers[0]);
794 $result = $assign->testable_process_add_attempt($this->students[0]->id);
795 $this->assertEquals(true, $result);
796
797 // Check that the previous attempt is now in the submission history table.
798 $this->setUser($this->students[0]);
799 $output = $assign->view_student_summary($this->students[0], true);
800 // Need a better check.
801 $this->assertNotEquals(false, strpos($output, 'Submission text'), 'Contains: Submission text');
802
803 // Check that the student now has a button for Add a new attempt".
804 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
805 // Check that the student now does not have a button for Submit.
806 $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign')));
807
808 // Check that the student now has a submission history.
809 $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign')));
810
811 $this->setUser($this->teachers[0]);
812 // Check that the grading table loads correctly and contains this user.
813 // This is also testing that we do not get duplicate rows in the grading table.
814 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
815 $output = $assign->get_renderer()->render($gradingtable);
816 $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
817
818 // Should be 1 not 2.
819 $this->assertEquals(1, $assign->count_submissions());
820 $this->assertEquals(1, $assign->count_submissions_with_status('reopened'));
821 $this->assertEquals(0, $assign->count_submissions_need_grading());
822 $this->assertEquals(1, $assign->count_grades());
823
824 // Change max attempts to unlimited.
825 $formdata = clone($assign->get_instance());
826 $formdata->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
827 $formdata->instance = $formdata->id;
828 $assign->update_instance($formdata);
829
830 // Check we can repopen still.
831 $result = $assign->testable_process_add_attempt($this->students[0]->id);
832 $this->assertEquals(true, $result);
833
834 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
835 $this->assertEquals(50, (int)$grades[$this->students[0]->id]->rawgrade);
836
df211804 837 }
46692c3a 838
f8d107b3
DM
839 public function test_markingworkflow() {
840 global $PAGE;
841
842 $this->setUser($this->editingteachers[0]);
843 $assign = $this->create_instance(array('markingworkflow'=>1));
844 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
845
13e82f1c 846 // Mark the submission and set to notmarked.
f8d107b3
DM
847 $this->setUser($this->teachers[0]);
848 $data = new stdClass();
849 $data->grade = '50.0';
850 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED;
851 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
852
853 // Check the student can't see the grade.
854 $this->setUser($this->students[0]);
855 $output = $assign->view_student_summary($this->students[0], true);
856 $this->assertEquals(false, strpos($output, '50.0'));
857
13e82f1c 858 // Mark the submission and set to inmarking.
f8d107b3
DM
859 $this->setUser($this->teachers[0]);
860 $data = new stdClass();
861 $data->grade = '50.0';
862 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INMARKING;
863 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
864
865 // Check the student can't see the grade.
866 $this->setUser($this->students[0]);
867 $output = $assign->view_student_summary($this->students[0], true);
868 $this->assertEquals(false, strpos($output, '50.0'));
869
13e82f1c 870 // Mark the submission and set to readyforreview.
f8d107b3
DM
871 $this->setUser($this->teachers[0]);
872 $data = new stdClass();
873 $data->grade = '50.0';
874 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW;
875 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
876
877 // Check the student can't see the grade.
878 $this->setUser($this->students[0]);
879 $output = $assign->view_student_summary($this->students[0], true);
880 $this->assertEquals(false, strpos($output, '50.0'));
881
13e82f1c 882 // Mark the submission and set to inreview.
f8d107b3
DM
883 $this->setUser($this->teachers[0]);
884 $data = new stdClass();
885 $data->grade = '50.0';
886 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW;
887 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
888
889 // Check the student can't see the grade.
890 $this->setUser($this->students[0]);
891 $output = $assign->view_student_summary($this->students[0], true);
892 $this->assertEquals(false, strpos($output, '50.0'));
893
13e82f1c 894 // Mark the submission and set to readyforrelease.
f8d107b3
DM
895 $this->setUser($this->teachers[0]);
896 $data = new stdClass();
897 $data->grade = '50.0';
898 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE;
899 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
900
901 // Check the student can't see the grade.
902 $this->setUser($this->students[0]);
903 $output = $assign->view_student_summary($this->students[0], true);
904 $this->assertEquals(false, strpos($output, '50.0'));
905
13e82f1c 906 // Mark the submission and set to released.
f8d107b3
DM
907 $this->setUser($this->teachers[0]);
908 $data = new stdClass();
909 $data->grade = '50.0';
910 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED;
911 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
912
913 // Check the student can see the grade.
914 $this->setUser($this->students[0]);
915 $output = $assign->view_student_summary($this->students[0], true);
916 $this->assertNotEquals(false, strpos($output, '50.0'));
917 }
918
919 public function test_markerallocation() {
920 global $PAGE;
921
922 $this->setUser($this->editingteachers[0]);
13e82f1c 923 $assign = $this->create_instance(array('markingworkflow'=>1, 'markingallocation'=>1));
f8d107b3
DM
924 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
925
13e82f1c 926 // Allocate marker to submission.
f8d107b3
DM
927 $data = new stdClass();
928 $data->allocatedmarker = $this->teachers[0]->id;
929 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
930
13e82f1c 931 // Check the allocated marker can view the submission.
f8d107b3
DM
932 $this->setUser($this->teachers[0]);
933 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
934 $output = $assign->get_renderer()->render($gradingtable);
935 $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
936
13e82f1c 937 // Check that other teachers can't view this submission.
f8d107b3
DM
938 $this->setUser($this->teachers[1]);
939 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
940 $output = $assign->get_renderer()->render($gradingtable);
941 $this->assertNotEquals(true, strpos($output, $this->students[0]->lastname));
942 }
76e77b05
FM
943
944 public function test_extension_granted_event() {
945 $this->setUser($this->editingteachers[0]);
946
947 $tomorrow = time() + 24*60*60;
948 $yesterday = time() - 24*60*60;
949
950 $assign = $this->create_instance(array('duedate' => $yesterday, 'cutoffdate' => $yesterday));
951 $sink = $this->redirectEvents();
952
953 $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
954
955 $events = $sink->get_events();
956 $this->assertCount(1, $events);
957 $event = reset($events);
958 $this->assertInstanceOf('\mod_assign\event\extension_granted', $event);
959 $this->assertEquals($assign->get_context(), $event->get_context());
960 $this->assertEquals($assign->get_instance()->id, $event->objectid);
961 $this->assertEquals($this->students[0]->id, $event->relateduserid);
962 $expected = array(
963 $assign->get_course()->id,
964 'assign',
965 'grant extension',
966 'view.php?id=' . $assign->get_course_module()->id,
967 $this->students[0]->id,
968 $assign->get_course_module()->id,
969 $this->editingteachers[0]->id
970 );
971 $this->assertEventLegacyLogData($expected, $event);
972 $sink->close();
973 }
974
3d1331be
FM
975 public function test_submission_locked_event() {
976 $this->editingteachers[0]->ignoresesskey = true;
977 $this->setUser($this->editingteachers[0]);
978
979 $assign = $this->create_instance();
980 $sink = $this->redirectEvents();
981
982 $assign->testable_process_lock($this->students[0]->id);
983
984 $events = $sink->get_events();
985 $this->assertCount(1, $events);
986 $event = reset($events);
987 $this->assertInstanceOf('\mod_assign\event\submission_locked', $event);
988 $this->assertEquals($assign->get_context(), $event->get_context());
989 $this->assertEquals($assign->get_instance()->id, $event->objectid);
990 $this->assertEquals($this->students[0]->id, $event->relateduserid);
991 $expected = array(
992 $assign->get_course()->id,
993 'assign',
994 'lock submission',
995 'view.php?id=' . $assign->get_course_module()->id,
996 get_string('locksubmissionforstudent', 'assign', array('id' => $this->students[0]->id,
997 'fullname' => fullname($this->students[0]))),
998 $assign->get_course_module()->id,
999 $this->editingteachers[0]->id
1000 );
1001 $this->assertEventLegacyLogData($expected, $event);
1002 $sink->close();
1003
1004 // Revert to defaults.
1005 $this->editingteachers[0]->ignoresesskey = false;
1006 }
1007
ad10ad14
FM
1008 public function test_identities_revealed_event() {
1009 $this->editingteachers[0]->ignoresesskey = true;
1010 $this->setUser($this->editingteachers[0]);
1011
1012 $assign = $this->create_instance(array('blindmarking'=>1));
1013 $sink = $this->redirectEvents();
1014
1015 $assign->testable_process_reveal_identities();
1016
1017 $events = $sink->get_events();
1018 $this->assertCount(1, $events);
1019 $event = reset($events);
1020 $this->assertInstanceOf('\mod_assign\event\identities_revealed', $event);
1021 $this->assertEquals($assign->get_context(), $event->get_context());
1022 $this->assertEquals($assign->get_instance()->id, $event->objectid);
1023 $expected = array(
1024 $assign->get_course()->id,
1025 'assign',
1026 'reveal identities',
1027 'view.php?id=' . $assign->get_course_module()->id,
1028 get_string('revealidentities', 'assign'),
1029 $assign->get_course_module()->id,
1030 $this->editingteachers[0]->id
1031 );
1032 $this->assertEventLegacyLogData($expected, $event);
1033 $sink->close();
1034
1035 // Revert to defaults.
1036 $this->editingteachers[0]->ignoresesskey = false;
1037 }
1038
47f48152
DW
1039}
1040