MDL-38047 Assignment unit tests - Shave 1 minute from the unit tests for mod_assign.
[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');
32
33/**
34 * Unit tests for (some of) mod/assign/locallib.php.
35 *
36 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 */
39class mod_assign_locallib_testcase extends advanced_testcase {
40
a5c793c3
DW
41 /** @const Default number of students to create */
42 const DEFAULT_STUDENT_COUNT = 3;
43 /** @const Default number of teachers to create */
44 const DEFAULT_TEACHER_COUNT = 2;
45 /** @const Default number of editing teachers to create */
46 const DEFAULT_EDITING_TEACHER_COUNT = 2;
47 /** @const Optional extra number of students to create */
48 const EXTRA_STUDENT_COUNT = 40;
49 /** @const Optional extra number of teachers to create */
50 const EXTRA_TEACHER_COUNT = 5;
51 /** @const Optional extra number of editing teachers to create */
52 const EXTRA_EDITING_TEACHER_COUNT = 5;
53 /** @const Number of groups to create */
54 const GROUP_COUNT = 6;
55
47f48152
DW
56 /** @var stdClass $course New course created to hold the assignments */
57 protected $course = null;
58
a5c793c3 59 /** @var array $teachers List of DEFAULT_TEACHER_COUNT teachers in the course*/
47f48152
DW
60 protected $teachers = null;
61
a5c793c3 62 /** @var array $editingteachers List of DEFAULT_EDITING_TEACHER_COUNT editing teachers in the course */
47f48152
DW
63 protected $editingteachers = null;
64
a5c793c3 65 /** @var array $students List of DEFAULT_STUDENT_COUNT students in the course*/
47f48152
DW
66 protected $students = null;
67
a5c793c3
DW
68 /** @var array $extrateachers List of EXTRA_TEACHER_COUNT teachers in the course*/
69 protected $extrateachers = null;
70
71 /** @var array $extraeditingteachers List of EXTRA_EDITING_TEACHER_COUNT editing teachers in the course*/
72 protected $extraeditingteachers = null;
73
74 /** @var array $extrastudents List of EXTRA_STUDENT_COUNT students in the course*/
75 protected $extrastudents = null;
76
47f48152
DW
77 /** @var array $groups List of 10 groups in the course */
78 protected $groups = null;
79
80 /**
81 * Setup function - we will create a course and add an assign instance to it.
82 */
83 protected function setUp() {
a5c793c3 84 global $DB;
47f48152
DW
85
86 $this->resetAfterTest(true);
87
88 $this->course = $this->getDataGenerator()->create_course();
89 $this->teachers = array();
a5c793c3 90 for ($i = 0; $i < self::DEFAULT_TEACHER_COUNT; $i++) {
47f48152
DW
91 array_push($this->teachers, $this->getDataGenerator()->create_user());
92 }
93
94 $this->editingteachers = array();
a5c793c3 95 for ($i = 0; $i < self::DEFAULT_EDITING_TEACHER_COUNT; $i++) {
47f48152
DW
96 array_push($this->editingteachers, $this->getDataGenerator()->create_user());
97 }
98
99 $this->students = array();
a5c793c3 100 for ($i = 0; $i < self::DEFAULT_STUDENT_COUNT; $i++) {
47f48152
DW
101 array_push($this->students, $this->getDataGenerator()->create_user());
102 }
103
104 $this->groups = array();
a5c793c3 105 for ($i = 0; $i < self::GROUP_COUNT; $i++) {
47f48152
DW
106 array_push($this->groups, $this->getDataGenerator()->create_group(array('courseid'=>$this->course->id)));
107 }
108
109 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
110 foreach ($this->teachers as $i => $teacher) {
111 $this->getDataGenerator()->enrol_user($teacher->id,
112 $this->course->id,
113 $teacherrole->id);
a5c793c3 114 groups_add_member($this->groups[$i % self::GROUP_COUNT], $teacher);
47f48152
DW
115 }
116
117 $editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
118 foreach ($this->editingteachers as $i => $editingteacher) {
119 $this->getDataGenerator()->enrol_user($editingteacher->id,
120 $this->course->id,
121 $editingteacherrole->id);
a5c793c3 122 groups_add_member($this->groups[$i % self::GROUP_COUNT], $editingteacher);
47f48152
DW
123 }
124
125 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
126 foreach ($this->students as $i => $student) {
127 $this->getDataGenerator()->enrol_user($student->id,
128 $this->course->id,
129 $studentrole->id);
a5c793c3
DW
130 groups_add_member($this->groups[$i % self::GROUP_COUNT], $student);
131 }
132 }
133
134 /*
135 * For tests that make sense to use alot of data, create extra students/teachers.
136 */
137 private function createExtraUsers() {
138 global $DB;
139 $this->extrateachers = array();
140 for ($i = 0; $i < self::EXTRA_TEACHER_COUNT; $i++) {
141 array_push($this->extrateachers, $this->getDataGenerator()->create_user());
142 }
143
144 $this->extraeditingteachers = array();
145 for ($i = 0; $i < self::EXTRA_EDITING_TEACHER_COUNT; $i++) {
146 array_push($this->extraeditingteachers, $this->getDataGenerator()->create_user());
147 }
148
149 $this->extrastudents = array();
150 for ($i = 0; $i < self::EXTRA_STUDENT_COUNT; $i++) {
151 array_push($this->extrastudents, $this->getDataGenerator()->create_user());
152 }
153
154 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
155 foreach ($this->extrateachers as $i => $teacher) {
156 $this->getDataGenerator()->enrol_user($teacher->id,
157 $this->course->id,
158 $teacherrole->id);
159 groups_add_member($this->groups[$i % self::GROUP_COUNT], $teacher);
160 }
161
162 $editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
163 foreach ($this->extraeditingteachers as $i => $editingteacher) {
164 $this->getDataGenerator()->enrol_user($editingteacher->id,
165 $this->course->id,
166 $editingteacherrole->id);
167 groups_add_member($this->groups[$i % self::GROUP_COUNT], $editingteacher);
168 }
169
170 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
171 foreach ($this->extrastudents as $i => $student) {
172 $this->getDataGenerator()->enrol_user($student->id,
173 $this->course->id,
174 $studentrole->id);
175 if ($i < (self::EXTRA_STUDENT_COUNT / 2)) {
176 groups_add_member($this->groups[$i % self::GROUP_COUNT], $student);
47f48152
DW
177 }
178 }
a5c793c3 179
47f48152
DW
180 }
181
182 private function create_instance($params=array()) {
183 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
184 $params['course'] = $this->course->id;
185 $instance = $generator->create_instance($params);
186 $cm = get_coursemodule_from_instance('assign', $instance->id);
187 $context = context_module::instance($cm->id);
188 return new testable_assign($context, $cm, $this->course);
189 }
190
191 public function test_return_links() {
192 $this->setUser($this->editingteachers[0]);
193 $returnaction = 'RETURNACTION';
194 $returnparams = array('param'=>1);
195 $assign = $this->create_instance();
196 $assign->register_return_link($returnaction, $returnparams);
197 $this->assertEquals($returnaction, $assign->get_return_action());
198 $this->assertEquals($returnparams, $assign->get_return_params());
199 }
200
201 public function test_get_feedback_plugins() {
202 $this->setUser($this->editingteachers[0]);
203 $assign = $this->create_instance();
204 $this->assertEquals(3, count($assign->get_feedback_plugins()));
205 }
206
207 public function test_get_submission_plugins() {
208 $this->setUser($this->editingteachers[0]);
209 $assign = $this->create_instance();
210 $this->assertEquals(3, count($assign->get_submission_plugins()));
211 }
212
213 public function test_is_blind_marking() {
214 $this->setUser($this->editingteachers[0]);
215 $assign = $this->create_instance(array('blindmarking'=>1));
216 $this->assertEquals(true, $assign->is_blind_marking());
217
218 // Test cannot see student names.
219 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
220 $output = $assign->get_renderer()->render($gradingtable);
221 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign')));
222
223 // Test students cannot reveal identities.
224 $nopermission = false;
225 $this->setUser($this->students[0]);
226 $this->setExpectedException('required_capability_exception');
227 $assign->testable_process_reveal_identities();
228
229 // Test teachers cannot reveal identities.
230 $nopermission = false;
231 $this->setUser($this->teachers[0]);
232 $this->setExpectedException('required_capability_exception');
233 $assign->testable_process_reveal_identities();
234
235 // Test sesskey is required.
236 $nosesskey = true;
237 $this->setUser($this->editingteachers[0]);
238 $this->setExpectedException('moodle_exception');
239 $assign->testable_process_reveal_identities();
240
241 // Test editingteacher can reveal identities if sesskey is ignored.
242 $this->editingteachers[0]->ignoresesskey = true;
243 $this->setUser($this->editingteachers[0]);
244 $assign->testable_process_reveal_identities();
245 $this->assertEquals(false, $assign->is_blind_marking());
246
247 // Test student names are visible.
248 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
249 $output = $assign->get_renderer()->render($gradingtable);
250 $this->assertEquals(false, strpos($output, get_string('hiddenuser', 'assign')));
251
252 // Set this back to default.
253 $this->editingteachers[0]->ignoresesskey = false;
254 }
255
256 public function test_show_intro() {
257 // Test whether we are showing the intro at the correct times.
258 $this->setUser($this->editingteachers[0]);
259 $assign = $this->create_instance(array('alwaysshowdescription'=>1));
260
261 $this->assertEquals(true, $assign->testable_show_intro());
262
263 $tomorrow = time() + (24*60*60);
264
265 $assign = $this->create_instance(array('alwaysshowdescription'=>0,
266 'allowsubmissionsfromdate'=>$tomorrow));
267 $this->assertEquals(false, $assign->testable_show_intro());
268 $yesterday = time() - (24*60*60);
269 $assign = $this->create_instance(array('alwaysshowdescription'=>0,
270 'allowsubmissionsfromdate'=>$yesterday));
271 $this->assertEquals(true, $assign->testable_show_intro());
272 }
273
274 public function test_has_submissions_or_grades() {
275 $this->setUser($this->editingteachers[0]);
276 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
277
278 $instance = $assign->get_instance();
279
280 // Should start empty.
281 $this->assertEquals(false, $assign->has_submissions_or_grades());
282
283 // Simulate a submission.
284 $this->setUser($this->students[0]);
285 $submission = $assign->get_user_submission($this->students[0]->id, true);
286 $data = new stdClass();
287 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
288 'text'=>'Submission text',
289 'format'=>FORMAT_MOODLE);
290 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
291 $plugin->save($submission, $data);
292
293 // Now test again.
294 $this->assertEquals(true, $assign->has_submissions_or_grades());
295 // Set this back to default.
296 $this->students[0]->ignoresesskey = false;
297 }
298
299 public function test_delete_grades() {
300 $this->setUser($this->editingteachers[0]);
301 $assign = $this->create_instance();
302
303 // Simulate adding a grade.
304 $this->setUser($this->teachers[0]);
305 $data = new stdClass();
306 $data->grade = '50.0';
307 $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
308
309 // Now see if the data is in the gradebook.
310 $gradinginfo = grade_get_grades($this->course->id,
311 'mod',
312 'assign',
313 $assign->get_instance()->id);
314
315 $this->assertNotEquals(0, count($gradinginfo->items));
316
317 $assign->testable_delete_grades();
318 $gradinginfo = grade_get_grades($this->course->id,
319 'mod',
320 'assign',
321 $assign->get_instance()->id);
322
323 $this->assertEquals(0, count($gradinginfo->items));
324 }
325
326 public function test_delete_instance() {
327 $this->setUser($this->editingteachers[0]);
328 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
329
330 // Simulate adding a grade.
331 $this->setUser($this->teachers[0]);
332 $data = new stdClass();
333 $data->grade = '50.0';
334 $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
335
336 // Simulate a submission.
337 $this->setUser($this->students[0]);
338 $submission = $assign->get_user_submission($this->students[0]->id, true);
339 $data = new stdClass();
340 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
341 'text'=>'Submission text',
342 'format'=>FORMAT_MOODLE);
343 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
344 $plugin->save($submission, $data);
345
346 // Now try and delete.
347 $this->assertEquals(true, $assign->delete_instance());
348 }
349
350 public function test_reset_userdata() {
351 global $DB;
352
353 $now = time();
354 $this->setUser($this->editingteachers[0]);
355 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1,
356 'duedate'=>$now));
357
358 // Simulate adding a grade.
359 $this->setUser($this->teachers[0]);
360 $data = new stdClass();
361 $data->grade = '50.0';
362 $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
363
364 // Simulate a submission.
365 $this->setUser($this->students[0]);
366 $submission = $assign->get_user_submission($this->students[0]->id, true);
367 $data = new stdClass();
368 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
369 'text'=>'Submission text',
370 'format'=>FORMAT_MOODLE);
371 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
372 $plugin->save($submission, $data);
373
374 $this->assertEquals(true, $assign->has_submissions_or_grades());
375 // Now try and reset.
376 $data = new stdClass();
377 $data->reset_assign_submissions = 1;
378 $data->reset_gradebook_grades = 1;
379 $data->courseid = $this->course->id;
380 $data->timeshift = 24*60*60;
381 $this->setUser($this->editingteachers[0]);
382 $assign->reset_userdata($data);
383 $this->assertEquals(false, $assign->has_submissions_or_grades());
384
385 // Reload the instance data.
386 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
387 $this->assertEquals($now + 24*60*60, $instance->duedate);
388 }
389
390 public function test_plugin_settings() {
391 global $DB;
392
393 $now = time();
394 $this->setUser($this->editingteachers[0]);
395 $assign = $this->create_instance(array('assignsubmission_file_enabled'=>1,
396 'assignsubmission_file_maxfiles'=>12,
397 'assignsubmission_file_maxsizebytes'=>10));
398
399 $plugin = $assign->get_submission_plugin_by_type('file');
400 $this->assertEquals('12', $plugin->get_config('maxfilesubmissions'));
401 }
402
403 public function test_update_calendar() {
404 global $DB;
405
406 $now = time();
407 $this->setUser($this->editingteachers[0]);
408 $assign = $this->create_instance(array('duedate'=>$now));
409
410 // See if there is an event in the calendar.
411 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
412 $id = $DB->get_field('event', 'id', $params);
413
414 $this->assertEquals(false, empty($id));
415 }
416
417 public function test_update_instance() {
418 global $DB;
419
420 $this->setUser($this->editingteachers[0]);
421 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
422
423 $now = time();
424 $instance = $assign->get_instance();
425 $instance->duedate = $now;
426 $instance->instance = $instance->id;
427 $instance->assignsubmission_onlinetext_enabled = 1;
428 $instance->assignsubmission_file_enabled = 0;
429 $instance->assignsubmission_comments_enabled = 0;
430 $instance->assignfeedback_comments_enabled = 0;
431 $instance->assignfeedback_file_enabled = 0;
432 $instance->assignfeedback_offline_enabled = 0;
433
434 $assign->update_instance($instance);
435
436 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
437 $this->assertEquals($now, $instance->duedate);
438 }
439
440 public function test_list_participants() {
a5c793c3 441 $this->createExtraUsers();
47f48152
DW
442 $this->setUser($this->editingteachers[0]);
443 $assign = $this->create_instance(array('grade'=>100));
444
a5c793c3 445 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
47f48152
DW
446 }
447
448 public function test_count_teams() {
a5c793c3 449 $this->createExtraUsers();
47f48152
DW
450 $this->setUser($this->editingteachers[0]);
451 $assign = $this->create_instance(array('teamsubmission'=>1));
452
a5c793c3 453 $this->assertEquals(self::GROUP_COUNT + 1, $assign->count_teams());
47f48152
DW
454 }
455
456 public function test_count_submissions() {
a5c793c3 457 $this->createExtraUsers();
47f48152
DW
458 $this->setUser($this->editingteachers[0]);
459 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
460
461 // Simulate a submission.
a5c793c3
DW
462 $this->setUser($this->extrastudents[0]);
463 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
47f48152
DW
464 // Leave this one as DRAFT.
465 $data = new stdClass();
466 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
467 'text'=>'Submission text',
468 'format'=>FORMAT_MOODLE);
469 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
470 $plugin->save($submission, $data);
471
472 // Simulate adding a grade.
473 $this->setUser($this->teachers[0]);
474 $data = new stdClass();
475 $data->grade = '50.0';
a5c793c3 476 $assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id);
47f48152
DW
477
478 // Simulate a submission.
a5c793c3
DW
479 $this->setUser($this->extrastudents[1]);
480 $submission = $assign->get_user_submission($this->extrastudents[1]->id, true);
47f48152 481 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
a5c793c3 482 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
47f48152
DW
483 $data = new stdClass();
484 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
485 'text'=>'Submission text',
486 'format'=>FORMAT_MOODLE);
487 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
488 $plugin->save($submission, $data);
489
490 // Simulate a submission.
a5c793c3
DW
491 $this->setUser($this->extrastudents[2]);
492 $submission = $assign->get_user_submission($this->extrastudents[2]->id, true);
47f48152 493 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
a5c793c3 494 $assign->testable_update_submission($submission, $this->extrastudents[2]->id, true, false);
47f48152
DW
495 $data = new stdClass();
496 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
497 'text'=>'Submission text',
498 'format'=>FORMAT_MOODLE);
499 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
500 $plugin->save($submission, $data);
501
502 // Simulate a submission.
a5c793c3
DW
503 $this->setUser($this->extrastudents[3]);
504 $submission = $assign->get_user_submission($this->extrastudents[3]->id, true);
47f48152 505 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
a5c793c3 506 $assign->testable_update_submission($submission, $this->extrastudents[3]->id, true, false);
47f48152
DW
507 $data = new stdClass();
508 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
509 'text'=>'Submission text',
510 'format'=>FORMAT_MOODLE);
511 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
512 $plugin->save($submission, $data);
513
514 // Simulate adding a grade.
515 $this->setUser($this->teachers[0]);
516 $data = new stdClass();
517 $data->grade = '50.0';
a5c793c3 518 $assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id);
47f48152
DW
519
520 $this->assertEquals(2, $assign->count_grades());
521 $this->assertEquals(4, $assign->count_submissions());
522 $this->assertEquals(2, $assign->count_submissions_need_grading());
523 $this->assertEquals(3, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
524 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
525 }
526
527 public function test_get_grading_userid_list() {
a5c793c3 528 $this->createExtraUsers();
47f48152
DW
529 $this->setUser($this->editingteachers[0]);
530 $assign = $this->create_instance();
531
532 $users = $assign->testable_get_grading_userid_list();
a5c793c3 533 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($users));
47f48152
DW
534 }
535
536 public function test_cron() {
537 // First run cron so there are no messages waiting to be sent (from other tests).
538 cron_setup_user();
539 assign::cron();
540
541 // Now create an assignment and add some feedback.
542 $this->setUser($this->editingteachers[0]);
543 $assign = $this->create_instance();
544
545 // Simulate adding a grade.
546 $this->setUser($this->teachers[0]);
547 $data = new stdClass();
548 $data->grade = '50.0';
a5c793c3 549 $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
47f48152
DW
550
551 // Now run cron and see that one message was sent.
552 $this->preventResetByRollback();
553 $sink = $this->redirectMessages();
554 cron_setup_user();
555 $this->expectOutputRegex('/Done processing 1 assignment submissions/');
556 assign::cron();
557
558 $messages = $sink->get_messages();
559 $this->assertEquals(1, count($messages));
560 $this->assertEquals(1, $messages[0]->notification);
561 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
562 }
563
564 public function test_is_graded() {
565 $this->setUser($this->editingteachers[0]);
566 $assign = $this->create_instance();
567
568 // Simulate adding a grade.
569 $this->setUser($this->teachers[0]);
570 $data = new stdClass();
571 $data->grade = '50.0';
572 $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
573
574 $this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id));
575 $this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
576 }
577
578 public function test_can_view_submission() {
579 $this->setUser($this->editingteachers[0]);
580 $assign = $this->create_instance();
581
582 $this->setUser($this->students[0]);
583 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
584 $this->assertEquals(false, $assign->can_view_submission($this->students[1]->id));
585 $this->assertEquals(false, $assign->can_view_submission($this->teachers[0]->id));
586 $this->setUser($this->teachers[0]);
587 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
588 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
589 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
590 $this->setUser($this->editingteachers[0]);
591 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
592 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
593 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
594 }
595
596
597 public function test_update_submission() {
a5c793c3 598 $this->createExtraUsers();
47f48152
DW
599 $this->setUser($this->editingteachers[0]);
600 $assign = $this->create_instance();
601
a5c793c3 602 $this->setUser($this->extrastudents[0]);
47f48152 603 $now = time();
a5c793c3
DW
604 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
605 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
606
607 $this->setUser($this->teachers[0]);
608 // Verify the gradebook update.
609 $gradinginfo = grade_get_grades($this->course->id,
610 'mod',
611 'assign',
612 $assign->get_instance()->id,
a5c793c3 613 $this->extrastudents[0]->id);
47f48152 614
a5c793c3
DW
615 $this->assertEquals($this->extrastudents[0]->id,
616 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
47f48152
DW
617
618 // Now verify group assignments.
619 $this->setUser($this->editingteachers[0]);
620 $assign = $this->create_instance(array('teamsubmission'=>1));
621
a5c793c3 622 $this->setUser($this->extrastudents[0]);
47f48152 623 $now = time();
a5c793c3
DW
624 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
625 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
47f48152
DW
626
627 // Check that at least 2 members of the submission group had their submission updated.
628
629 $this->setUser($this->editingteachers[0]);
630 $gradinginfo = grade_get_grades($this->course->id,
631 'mod',
632 'assign',
633 $assign->get_instance()->id,
a5c793c3 634 $this->extrastudents[0]->id);
47f48152 635
a5c793c3
DW
636 $this->assertEquals($this->extrastudents[0]->id,
637 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
47f48152
DW
638
639 $gradinginfo = grade_get_grades($this->course->id,
640 'mod',
641 'assign',
642 $assign->get_instance()->id,
a5c793c3 643 $this->extrastudents[self::GROUP_COUNT]->id);
47f48152 644
a5c793c3
DW
645 $this->assertEquals($this->extrastudents[self::GROUP_COUNT]->id,
646 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT]->id]->usermodified);
47f48152
DW
647
648 // Now verify blind marking.
649 $this->setUser($this->editingteachers[0]);
650 $assign = $this->create_instance(array('blindmarking'=>1));
651
a5c793c3 652 $this->setUser($this->extrastudents[0]);
47f48152 653 $now = time();
a5c793c3
DW
654 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
655 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
656
657 $this->setUser($this->editingteachers[0]);
658 $gradinginfo = grade_get_grades($this->course->id,
659 'mod',
660 'assign',
661 $assign->get_instance()->id,
a5c793c3 662 $this->extrastudents[0]->id);
47f48152 663
a5c793c3 664 $this->assertEquals(null, $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->datesubmitted);
47f48152
DW
665 }
666
667 public function test_submissions_open() {
668 $this->setUser($this->editingteachers[0]);
669
670 $now = time();
671 $tomorrow = $now + 24*60*60;
672 $oneweek = $now + 7*24*60*60;
673 $yesterday = $now - 24*60*60;
674
675 $assign = $this->create_instance();
676 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
677
678 $assign = $this->create_instance(array('duedate'=>$tomorrow));
679 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
680
681 $assign = $this->create_instance(array('duedate'=>$yesterday));
682 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
683
684 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$tomorrow));
685 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
686
687 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$yesterday));
688 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
689
690 $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
691 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
692
693 $assign = $this->create_instance(array('submissiondrafts'=>1));
694 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
695
696 $this->setUser($this->students[0]);
697 $now = time();
698 $submission = $assign->get_user_submission($this->students[0]->id, true);
699 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
700 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
701 $this->setUser($this->editingteachers[0]);
702 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
703 }
704
705 public function test_get_graders() {
a5c793c3 706 $this->createExtraUsers();
47f48152
DW
707 $this->setUser($this->editingteachers[0]);
708 $assign = $this->create_instance();
709
a5c793c3
DW
710 $this->assertCount(self::DEFAULT_TEACHER_COUNT +
711 self::DEFAULT_EDITING_TEACHER_COUNT +
712 self::EXTRA_TEACHER_COUNT +
713 self::EXTRA_EDITING_TEACHER_COUNT,
714 $assign->testable_get_graders($this->students[0]->id));
47f48152
DW
715
716 $assign = $this->create_instance();
717 // Force create an assignment with SEPARATEGROUPS.
718 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
719 $params = array('course'=>$this->course->id);
720 $instance = $generator->create_instance($params);
721 $cm = get_coursemodule_from_instance('assign', $instance->id);
722 set_coursemodule_groupmode($cm->id, SEPARATEGROUPS);
723 $cm->groupmode = SEPARATEGROUPS;
724 $context = context_module::instance($cm->id);
725 $assign = new testable_assign($context, $cm, $this->course);
726
727 $this->setUser($this->students[1]);
a5c793c3 728 $this->assertCount(4, $assign->testable_get_graders($this->students[0]->id));
47f48152
DW
729 }
730
731 public function test_get_uniqueid_for_user() {
732 $this->setUser($this->editingteachers[0]);
733 $assign = $this->create_instance();
734
735 foreach ($this->students as $student) {
736 $uniqueid = $assign->get_uniqueid_for_user($student->id);
737 $this->assertEquals($student->id, $assign->get_user_id_for_uniqueid($uniqueid));
738 }
739 }
740
46692c3a
DW
741 public function test_show_student_summary() {
742 global $CFG;
743
744 $this->setUser($this->editingteachers[0]);
745 $assign = $this->create_instance();
746
747 // No feedback should be available because this student has not been graded.
748 $this->setUser($this->students[0]);
749 $output = $assign->view_student_summary($this->students[0], true);
750 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if there is no grade');
751 // Simulate adding a grade.
752 $this->setUser($this->teachers[0]);
753 $data = new stdClass();
754 $data->grade = '50.0';
755 $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
756
757 // Now we should see the feedback
758 $this->setUser($this->students[0]);
759 $output = $assign->view_student_summary($this->students[0], true);
760 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback if there is a grade');
761
762 // Now hide the grade in gradebook.
763 $this->setUser($this->teachers[0]);
764 require_once($CFG->libdir.'/gradelib.php');
765 $gradeitem = new grade_item(array(
766 'itemtype' => 'mod',
767 'itemmodule' => 'assign',
768 'iteminstance' => $assign->get_instance()->id,
769 'courseid' => $this->course->id));
770
771 $gradeitem->set_hidden(1, false);
772
773 // No feedback should be available because the grade is hidden.
774 $this->setUser($this->students[0]);
775 $output = $assign->view_student_summary($this->students[0], true);
776 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
777
778 // Do the same but add feedback
779 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
780
781 $this->setUser($this->teachers[0]);
782 $grade = $assign->get_user_grade($this->students[0]->id, true);
783 $data = new stdClass();
784 $data->assignfeedbackcomments_editor = array('text'=>'Tomato sauce',
785 'format'=>FORMAT_MOODLE);
786 $plugin = $assign->get_feedback_plugin_by_type('comments');
787 $plugin->save($grade, $data);
788
789 // Should have feedback but no grade
790 $this->setUser($this->students[0]);
791 $output = $assign->view_student_summary($this->students[0], true);
792 $this->assertNotEquals(false, strpos($output, 'Tomato sauce'), 'Show feedback even if there is no grade');
793 $this->assertEquals(false, strpos($output, 'Grade'), 'Do not show grade when there is no grade.');
794 $this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.');
795 }
796
797
47f48152
DW
798}
799
800/**
801 * Test subclass that makes all the protected methods we want to test public.
802 */
803class testable_assign extends assign {
804
805 public function testable_process_reveal_identities() {
806 return parent::process_reveal_identities();
807 }
808
809 public function testable_show_intro() {
810 return parent::show_intro();
811 }
812
813 public function testable_delete_grades() {
814 return parent::delete_grades();
815 }
816
817 public function testable_apply_grade_to_user($formdata, $userid) {
818 return parent::apply_grade_to_user($formdata, $userid);
819 }
820
821 public function testable_get_grading_userid_list() {
822 return parent::get_grading_userid_list();
823 }
824
825 public function testable_is_graded($userid) {
826 return parent::is_graded($userid);
827 }
828
829 public function testable_update_submission(stdClass $submission, $userid, $updatetime, $teamsubmission) {
830 return parent::update_submission($submission, $userid, $updatetime, $teamsubmission);
831 }
832
833 public function testable_submissions_open($userid = 0) {
834 return parent::submissions_open($userid);
835 }
836
837 public function testable_save_user_extension($userid, $extensionduedate) {
838 return parent::save_user_extension($userid, $extensionduedate);
839 }
840
841 public function testable_get_graders($userid) {
842 // Changed method from protected to public.
843 return parent::get_graders($userid);
844 }
845}