MDL-55609 mod_assign: Remove shared setUp for all tests
[moodle.git] / mod / assign / tests / events_test.php
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/>.
17 /**
18  * Contains the event tests for the module assign.
19  *
20  * @package   mod_assign
21  * @copyright 2014 Adrian Greeve <adrian@moodle.com>
22  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
27 global $CFG;
28 require_once($CFG->dirroot . '/mod/assign/tests/generator.php');
29 require_once($CFG->dirroot . '/mod/assign/tests/fixtures/event_mod_assign_fixtures.php');
30 require_once($CFG->dirroot . '/mod/assign/locallib.php');
32 /**
33  * Contains the event tests for the module assign.
34  *
35  * @package   mod_assign
36  * @copyright 2014 Adrian Greeve <adrian@moodle.com>
37  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class assign_events_testcase extends advanced_testcase {
40     // Use the generator helper.
41     use mod_assign_test_generator;
43     /**
44      * Basic tests for the submission_created() abstract class.
45      */
46     public function test_base_event() {
47         $this->resetAfterTest();
49         $course = $this->getDataGenerator()->create_course();
50         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
51         $instance = $generator->create_instance(array('course' => $course->id));
52         $modcontext = context_module::instance($instance->cmid);
54         $data = array(
55             'context' => $modcontext,
56         );
58         $event = \mod_assign_unittests\event\nothing_happened::create($data);
59         $assign = $event->get_assign();
60         $this->assertDebuggingCalled();
61         $this->assertInstanceOf('assign', $assign);
63         $event = \mod_assign_unittests\event\nothing_happened::create($data);
64         $event->set_assign($assign);
65         $assign2 = $event->get_assign();
66         $this->assertDebuggingNotCalled();
67         $this->assertSame($assign, $assign2);
68     }
70     /**
71      * Basic tests for the submission_created() abstract class.
72      */
73     public function test_submission_created() {
74         $this->resetAfterTest();
76         $course = $this->getDataGenerator()->create_course();
77         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
78         $instance = $generator->create_instance(array('course' => $course->id));
79         $modcontext = context_module::instance($instance->cmid);
81         // Standard Event parameters.
82         $params = array(
83             'context' => $modcontext,
84             'courseid' => $course->id
85         );
87         $eventinfo = $params;
88         $eventinfo['other'] = array(
89             'submissionid' => '17',
90             'submissionattempt' => 0,
91             'submissionstatus' => 'submitted'
92         );
94         $sink = $this->redirectEvents();
95         $event = \mod_assign_unittests\event\submission_created::create($eventinfo);
96         $event->trigger();
97         $result = $sink->get_events();
98         $event = reset($result);
99         $sink->close();
101         $this->assertEquals($modcontext->id, $event->contextid);
102         $this->assertEquals($course->id, $event->courseid);
104         // Check that an error occurs when teamsubmission is not set.
105         try {
106             \mod_assign_unittests\event\submission_created::create($params);
107             $this->fail('Other must contain the key submissionid.');
108         } catch (Exception $e) {
109             $this->assertInstanceOf('coding_exception', $e);
110         }
111         // Check that the submission status debugging is fired.
112         $subinfo = $params;
113         $subinfo['other'] = array('submissionid' => '23');
114         try {
115             \mod_assign_unittests\event\submission_created::create($subinfo);
116             $this->fail('Other must contain the key submissionattempt.');
117         } catch (Exception $e) {
118             $this->assertInstanceOf('coding_exception', $e);
119         }
121         $subinfo['other'] = array('submissionattempt' => '0');
122         try {
123             \mod_assign_unittests\event\submission_created::create($subinfo);
124             $this->fail('Other must contain the key submissionstatus.');
125         } catch (Exception $e) {
126             $this->assertInstanceOf('coding_exception', $e);
127         }
128     }
130     /**
131      * Basic tests for the submission_updated() abstract class.
132      */
133     public function test_submission_updated() {
134         $this->resetAfterTest();
136         $course = $this->getDataGenerator()->create_course();
137         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
138         $instance = $generator->create_instance(array('course' => $course->id));
139         $modcontext = context_module::instance($instance->cmid);
141         // Standard Event parameters.
142         $params = array(
143             'context' => $modcontext,
144             'courseid' => $course->id
145         );
147         $eventinfo = $params;
148         $eventinfo['other'] = array(
149             'submissionid' => '17',
150             'submissionattempt' => 0,
151             'submissionstatus' => 'submitted'
152         );
154         $sink = $this->redirectEvents();
155         $event = \mod_assign_unittests\event\submission_updated::create($eventinfo);
156         $event->trigger();
157         $result = $sink->get_events();
158         $event = reset($result);
159         $sink->close();
161         $this->assertEquals($modcontext->id, $event->contextid);
162         $this->assertEquals($course->id, $event->courseid);
164         // Check that an error occurs when teamsubmission is not set.
165         try {
166             \mod_assign_unittests\event\submission_created::create($params);
167             $this->fail('Other must contain the key submissionid.');
168         } catch (Exception $e) {
169             $this->assertInstanceOf('coding_exception', $e);
170         }
171         // Check that the submission status debugging is fired.
172         $subinfo = $params;
173         $subinfo['other'] = array('submissionid' => '23');
174         try {
175             \mod_assign_unittests\event\submission_created::create($subinfo);
176             $this->fail('Other must contain the key submissionattempt.');
177         } catch (Exception $e) {
178             $this->assertInstanceOf('coding_exception', $e);
179         }
181         $subinfo['other'] = array('submissionattempt' => '0');
182         try {
183             \mod_assign_unittests\event\submission_created::create($subinfo);
184             $this->fail('Other must contain the key submissionstatus.');
185         } catch (Exception $e) {
186             $this->assertInstanceOf('coding_exception', $e);
187         }
188     }
190     public function test_extension_granted() {
191         $this->resetAfterTest();
193         $course = $this->getDataGenerator()->create_course();
194         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
195         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
197         $this->setUser($teacher);
199         $now = time();
200         $tomorrow = $now + DAYSECS;
201         $yesterday = $now - DAYSECS;
203         $assign = $this->create_instance($course, [
204             'duedate' => $yesterday,
205             'cutoffdate' => $yesterday,
206         ]);
207         $sink = $this->redirectEvents();
209         $assign->testable_save_user_extension($student->id, $tomorrow);
211         $events = $sink->get_events();
212         $this->assertCount(1, $events);
213         $event = reset($events);
214         $this->assertInstanceOf('\mod_assign\event\extension_granted', $event);
215         $this->assertEquals($assign->get_context(), $event->get_context());
216         $this->assertEquals($assign->get_instance()->id, $event->objectid);
217         $this->assertEquals($student->id, $event->relateduserid);
219         $expected = array(
220             $assign->get_course()->id,
221             'assign',
222             'grant extension',
223             'view.php?id=' . $assign->get_course_module()->id,
224             $student->id,
225             $assign->get_course_module()->id
226         );
227         $this->assertEventLegacyLogData($expected, $event);
228         $sink->close();
229     }
231     public function test_submission_locked() {
232         $this->resetAfterTest();
234         $course = $this->getDataGenerator()->create_course();
235         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
236         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
238         $teacher->ignoresesskey = true;
239         $this->setUser($teacher);
241         $assign = $this->create_instance($course);
242         $sink = $this->redirectEvents();
244         $assign->lock_submission($student->id);
246         $events = $sink->get_events();
247         $this->assertCount(1, $events);
248         $event = reset($events);
249         $this->assertInstanceOf('\mod_assign\event\submission_locked', $event);
250         $this->assertEquals($assign->get_context(), $event->get_context());
251         $this->assertEquals($assign->get_instance()->id, $event->objectid);
252         $this->assertEquals($student->id, $event->relateduserid);
253         $expected = array(
254             $assign->get_course()->id,
255             'assign',
256             'lock submission',
257             'view.php?id=' . $assign->get_course_module()->id,
258             get_string('locksubmissionforstudent', 'assign', array('id' => $student->id,
259                 'fullname' => fullname($student))),
260             $assign->get_course_module()->id
261         );
262         $this->assertEventLegacyLogData($expected, $event);
263         $sink->close();
264     }
266     public function test_identities_revealed() {
267         $this->resetAfterTest();
269         $course = $this->getDataGenerator()->create_course();
270         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
272         $teacher->ignoresesskey = true;
273         $this->setUser($teacher);
275         $assign = $this->create_instance($course, ['blindmarking' => 1]);
276         $sink = $this->redirectEvents();
278         $assign->reveal_identities();
280         $events = $sink->get_events();
281         $this->assertCount(1, $events);
282         $event = reset($events);
283         $this->assertInstanceOf('\mod_assign\event\identities_revealed', $event);
284         $this->assertEquals($assign->get_context(), $event->get_context());
285         $this->assertEquals($assign->get_instance()->id, $event->objectid);
286         $expected = array(
287             $assign->get_course()->id,
288             'assign',
289             'reveal identities',
290             'view.php?id=' . $assign->get_course_module()->id,
291             get_string('revealidentities', 'assign'),
292             $assign->get_course_module()->id
293         );
294         $this->assertEventLegacyLogData($expected, $event);
295         $sink->close();
296     }
298     /**
299      * Test the submission_status_viewed event.
300      */
301     public function test_submission_status_viewed() {
302         global $PAGE;
303         $this->resetAfterTest();
305         $course = $this->getDataGenerator()->create_course();
306         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
308         $this->setUser($teacher);
310         $assign = $this->create_instance($course);
312         // We need to set the URL in order to view the feedback.
313         $PAGE->set_url('/a_url');
315         // Trigger and capture the event.
316         $sink = $this->redirectEvents();
317         $assign->view();
318         $events = $sink->get_events();
319         $this->assertCount(1, $events);
320         $event = reset($events);
322         // Check that the event contains the expected values.
323         $this->assertInstanceOf('\mod_assign\event\submission_status_viewed', $event);
324         $this->assertEquals($assign->get_context(), $event->get_context());
325         $expected = array(
326             $assign->get_course()->id,
327             'assign',
328             'view',
329             'view.php?id=' . $assign->get_course_module()->id,
330             get_string('viewownsubmissionstatus', 'assign'),
331             $assign->get_course_module()->id
332         );
333         $this->assertEventLegacyLogData($expected, $event);
334         $this->assertEventContextNotUsed($event);
335     }
337     public function test_submission_status_updated() {
338         $this->resetAfterTest();
340         $course = $this->getDataGenerator()->create_course();
341         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
342         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
344         $this->setUser($teacher);
346         $assign = $this->create_instance($course);
347         $submission = $assign->get_user_submission($student->id, true);
348         $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
349         $assign->testable_update_submission($submission, $student->id, true, false);
351         $sink = $this->redirectEvents();
352         $assign->revert_to_draft($student->id);
354         $events = $sink->get_events();
355         $this->assertCount(2, $events);
356         $event = $events[1];
357         $this->assertInstanceOf('\mod_assign\event\submission_status_updated', $event);
358         $this->assertEquals($assign->get_context(), $event->get_context());
359         $this->assertEquals($submission->id, $event->objectid);
360         $this->assertEquals($student->id, $event->relateduserid);
361         $this->assertEquals(ASSIGN_SUBMISSION_STATUS_DRAFT, $event->other['newstatus']);
362         $expected = array(
363             $assign->get_course()->id,
364             'assign',
365             'revert submission to draft',
366             'view.php?id=' . $assign->get_course_module()->id,
367             get_string('reverttodraftforstudent', 'assign', array('id' => $student->id,
368                 'fullname' => fullname($student))),
369             $assign->get_course_module()->id
370         );
371         $this->assertEventLegacyLogData($expected, $event);
372         $sink->close();
373     }
375     public function test_marker_updated() {
376         $this->resetAfterTest();
378         $course = $this->getDataGenerator()->create_course();
379         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
380         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
382         $teacher->ignoresesskey = true;
383         $this->setUser($teacher);
385         $assign = $this->create_instance($course);
387         $sink = $this->redirectEvents();
388         $assign->testable_process_set_batch_marking_allocation($student->id, $teacher->id);
390         $events = $sink->get_events();
391         $this->assertCount(1, $events);
392         $event = reset($events);
393         $this->assertInstanceOf('\mod_assign\event\marker_updated', $event);
394         $this->assertEquals($assign->get_context(), $event->get_context());
395         $this->assertEquals($assign->get_instance()->id, $event->objectid);
396         $this->assertEquals($student->id, $event->relateduserid);
397         $this->assertEquals($teacher->id, $event->userid);
398         $this->assertEquals($teacher->id, $event->other['markerid']);
399         $expected = array(
400             $assign->get_course()->id,
401             'assign',
402             'set marking allocation',
403             'view.php?id=' . $assign->get_course_module()->id,
404             get_string('setmarkerallocationforlog', 'assign', array('id' => $student->id,
405                 'fullname' => fullname($student), 'marker' => fullname($teacher))),
406             $assign->get_course_module()->id
407         );
408         $this->assertEventLegacyLogData($expected, $event);
409         $sink->close();
410     }
412     public function test_workflow_state_updated() {
413         $this->resetAfterTest();
415         $course = $this->getDataGenerator()->create_course();
416         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
417         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
419         $teacher->ignoresesskey = true;
420         $this->setUser($teacher);
422         $assign = $this->create_instance($course);
424         // Test process_set_batch_marking_workflow_state.
425         $sink = $this->redirectEvents();
426         $assign->testable_process_set_batch_marking_workflow_state($student->id, ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW);
428         $events = $sink->get_events();
429         $this->assertCount(1, $events);
430         $event = reset($events);
431         $this->assertInstanceOf('\mod_assign\event\workflow_state_updated', $event);
432         $this->assertEquals($assign->get_context(), $event->get_context());
433         $this->assertEquals($assign->get_instance()->id, $event->objectid);
434         $this->assertEquals($student->id, $event->relateduserid);
435         $this->assertEquals($teacher->id, $event->userid);
436         $this->assertEquals(ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW, $event->other['newstate']);
437         $expected = array(
438             $assign->get_course()->id,
439             'assign',
440             'set marking workflow state',
441             'view.php?id=' . $assign->get_course_module()->id,
442             get_string('setmarkingworkflowstateforlog', 'assign', array('id' => $student->id,
443                 'fullname' => fullname($student), 'state' => ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW)),
444             $assign->get_course_module()->id
445         );
446         $this->assertEventLegacyLogData($expected, $event);
447         $sink->close();
449         // Test setting workflow state in apply_grade_to_user.
450         $sink = $this->redirectEvents();
451         $data = new stdClass();
452         $data->grade = '50.0';
453         $data->workflowstate = 'readyforrelease';
454         $assign->testable_apply_grade_to_user($data, $student->id, 0);
456         $events = $sink->get_events();
457         $this->assertCount(4, $events);
458         $event = reset($events);
459         $this->assertInstanceOf('\mod_assign\event\workflow_state_updated', $event);
460         $this->assertEquals($assign->get_context(), $event->get_context());
461         $this->assertEquals($assign->get_instance()->id, $event->objectid);
462         $this->assertEquals($student->id, $event->relateduserid);
463         $this->assertEquals($teacher->id, $event->userid);
464         $this->assertEquals(ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE, $event->other['newstate']);
465         $expected = array(
466             $assign->get_course()->id,
467             'assign',
468             'set marking workflow state',
469             'view.php?id=' . $assign->get_course_module()->id,
470             get_string('setmarkingworkflowstateforlog', 'assign', array('id' => $student->id,
471                 'fullname' => fullname($student), 'state' => ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE)),
472             $assign->get_course_module()->id
473         );
474         $this->assertEventLegacyLogData($expected, $event);
475         $sink->close();
477         // Test setting workflow state in process_save_quick_grades.
478         $sink = $this->redirectEvents();
480         $data = array(
481             'grademodified_' . $student->id => time(),
482             'gradeattempt_' . $student->id => '',
483             'quickgrade_' . $student->id => '60.0',
484             'quickgrade_' . $student->id . '_workflowstate' => 'inmarking'
485         );
486         $assign->testable_process_save_quick_grades($data);
488         $events = $sink->get_events();
489         $this->assertCount(4, $events);
490         $event = reset($events);
491         $this->assertInstanceOf('\mod_assign\event\workflow_state_updated', $event);
492         $this->assertEquals($assign->get_context(), $event->get_context());
493         $this->assertEquals($assign->get_instance()->id, $event->objectid);
494         $this->assertEquals($student->id, $event->relateduserid);
495         $this->assertEquals($teacher->id, $event->userid);
496         $this->assertEquals(ASSIGN_MARKING_WORKFLOW_STATE_INMARKING, $event->other['newstate']);
497         $expected = array(
498             $assign->get_course()->id,
499             'assign',
500             'set marking workflow state',
501             'view.php?id=' . $assign->get_course_module()->id,
502             get_string('setmarkingworkflowstateforlog', 'assign', array('id' => $student->id,
503                 'fullname' => fullname($student), 'state' => ASSIGN_MARKING_WORKFLOW_STATE_INMARKING)),
504             $assign->get_course_module()->id
505         );
506         $this->assertEventLegacyLogData($expected, $event);
507         $sink->close();
508     }
510     public function test_submission_duplicated() {
511         $this->resetAfterTest();
513         $course = $this->getDataGenerator()->create_course();
514         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
516         $this->setUser($student);
518         $assign = $this->create_instance($course);
519         $submission1 = $assign->get_user_submission($student->id, true, 0);
520         $submission2 = $assign->get_user_submission($student->id, true, 1);
521         $submission2->status = ASSIGN_SUBMISSION_STATUS_REOPENED;
522         $assign->testable_update_submission($submission2, $student->id, time(), $assign->get_instance()->teamsubmission);
524         $sink = $this->redirectEvents();
525         $notices = null;
526         $assign->copy_previous_attempt($notices);
528         $events = $sink->get_events();
529         $this->assertCount(1, $events);
530         $event = reset($events);
531         $this->assertInstanceOf('\mod_assign\event\submission_duplicated', $event);
532         $this->assertEquals($assign->get_context(), $event->get_context());
533         $this->assertEquals($submission2->id, $event->objectid);
534         $this->assertEquals($student->id, $event->userid);
535         $submission2->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
536         $expected = array(
537             $assign->get_course()->id,
538             'assign',
539             'submissioncopied',
540             'view.php?id=' . $assign->get_course_module()->id,
541             $assign->testable_format_submission_for_log($submission2),
542             $assign->get_course_module()->id
543         );
544         $this->assertEventLegacyLogData($expected, $event);
545         $sink->close();
546     }
548     public function test_submission_unlocked() {
549         $this->resetAfterTest();
551         $course = $this->getDataGenerator()->create_course();
552         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
553         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
555         $teacher->ignoresesskey = true;
556         $this->setUser($teacher);
558         $assign = $this->create_instance($course);
559         $sink = $this->redirectEvents();
561         $assign->unlock_submission($student->id);
563         $events = $sink->get_events();
564         $this->assertCount(1, $events);
565         $event = reset($events);
566         $this->assertInstanceOf('\mod_assign\event\submission_unlocked', $event);
567         $this->assertEquals($assign->get_context(), $event->get_context());
568         $this->assertEquals($assign->get_instance()->id, $event->objectid);
569         $this->assertEquals($student->id, $event->relateduserid);
570         $expected = array(
571             $assign->get_course()->id,
572             'assign',
573             'unlock submission',
574             'view.php?id=' . $assign->get_course_module()->id,
575             get_string('unlocksubmissionforstudent', 'assign', array('id' => $student->id,
576                 'fullname' => fullname($student))),
577             $assign->get_course_module()->id
578         );
579         $this->assertEventLegacyLogData($expected, $event);
580         $sink->close();
581     }
583     public function test_submission_graded() {
584         $this->resetAfterTest();
586         $course = $this->getDataGenerator()->create_course();
587         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
588         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
590         $teacher->ignoresesskey = true;
591         $this->setUser($teacher);
593         $assign = $this->create_instance($course);
595         // Test apply_grade_to_user.
596         $sink = $this->redirectEvents();
598         $data = new stdClass();
599         $data->grade = '50.0';
600         $assign->testable_apply_grade_to_user($data, $student->id, 0);
601         $grade = $assign->get_user_grade($student->id, false, 0);
603         $events = $sink->get_events();
604         $this->assertCount(3, $events);
605         $event = $events[2];
606         $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
607         $this->assertEquals($assign->get_context(), $event->get_context());
608         $this->assertEquals($grade->id, $event->objectid);
609         $this->assertEquals($student->id, $event->relateduserid);
610         $expected = array(
611             $assign->get_course()->id,
612             'assign',
613             'grade submission',
614             'view.php?id=' . $assign->get_course_module()->id,
615             $assign->format_grade_for_log($grade),
616             $assign->get_course_module()->id
617         );
618         $this->assertEventLegacyLogData($expected, $event);
619         $sink->close();
621         // Test process_save_quick_grades.
622         $sink = $this->redirectEvents();
624         $grade = $assign->get_user_grade($student->id, false);
625         $data = array(
626             'grademodified_' . $student->id => time(),
627             'gradeattempt_' . $student->id => $grade->attemptnumber,
628             'quickgrade_' . $student->id => '60.0'
629         );
630         $assign->testable_process_save_quick_grades($data);
631         $grade = $assign->get_user_grade($student->id, false);
632         $this->assertEquals('60.0', $grade->grade);
634         $events = $sink->get_events();
635         $this->assertCount(3, $events);
636         $event = $events[2];
637         $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
638         $this->assertEquals($assign->get_context(), $event->get_context());
639         $this->assertEquals($grade->id, $event->objectid);
640         $this->assertEquals($student->id, $event->relateduserid);
641         $expected = array(
642             $assign->get_course()->id,
643             'assign',
644             'grade submission',
645             'view.php?id=' . $assign->get_course_module()->id,
646             $assign->format_grade_for_log($grade),
647             $assign->get_course_module()->id
648         );
649         $this->assertEventLegacyLogData($expected, $event);
650         $sink->close();
652         // Test update_grade.
653         $sink = $this->redirectEvents();
654         $data = clone($grade);
655         $data->grade = '50.0';
656         $assign->update_grade($data);
657         $grade = $assign->get_user_grade($student->id, false, 0);
658         $this->assertEquals('50.0', $grade->grade);
659         $events = $sink->get_events();
661         $this->assertCount(3, $events);
662         $event = $events[2];
663         $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
664         $this->assertEquals($assign->get_context(), $event->get_context());
665         $this->assertEquals($grade->id, $event->objectid);
666         $this->assertEquals($student->id, $event->relateduserid);
667         $expected = array(
668             $assign->get_course()->id,
669             'assign',
670             'grade submission',
671             'view.php?id=' . $assign->get_course_module()->id,
672             $assign->format_grade_for_log($grade),
673             $assign->get_course_module()->id
674         );
675         $this->assertEventLegacyLogData($expected, $event);
676         $sink->close();
677     }
679     /**
680      * Test the submission_viewed event.
681      */
682     public function test_submission_viewed() {
683         global $PAGE;
685         $this->resetAfterTest();
687         $course = $this->getDataGenerator()->create_course();
688         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
689         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
691         $this->setUser($teacher);
693         $assign = $this->create_instance($course);
694         $submission = $assign->get_user_submission($student->id, true);
696         // We need to set the URL in order to view the submission.
697         $PAGE->set_url('/a_url');
698         // A hack - these variables are used by the view_plugin_content function to
699         // determine what we actually want to view - would usually be set in URL.
700         global $_POST;
701         $_POST['plugin'] = 'comments';
702         $_POST['sid'] = $submission->id;
704         // Trigger and capture the event.
705         $sink = $this->redirectEvents();
706         $assign->view('viewpluginassignsubmission');
707         $events = $sink->get_events();
708         $this->assertCount(1, $events);
709         $event = reset($events);
711         // Check that the event contains the expected values.
712         $this->assertInstanceOf('\mod_assign\event\submission_viewed', $event);
713         $this->assertEquals($assign->get_context(), $event->get_context());
714         $this->assertEquals($submission->id, $event->objectid);
715         $expected = array(
716             $assign->get_course()->id,
717             'assign',
718             'view submission',
719             'view.php?id=' . $assign->get_course_module()->id,
720             get_string('viewsubmissionforuser', 'assign', $student->id),
721             $assign->get_course_module()->id
722         );
723         $this->assertEventLegacyLogData($expected, $event);
724         $this->assertEventContextNotUsed($event);
725     }
727     /**
728      * Test the feedback_viewed event.
729      */
730     public function test_feedback_viewed() {
731         global $DB, $PAGE;
733         $this->resetAfterTest();
735         $course = $this->getDataGenerator()->create_course();
736         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
737         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
739         $this->setUser($teacher);
741         $assign = $this->create_instance($course);
742         $submission = $assign->get_user_submission($student->id, true);
744         // Insert a grade for this submission.
745         $grade = new stdClass();
746         $grade->assignment = $assign->get_instance()->id;
747         $grade->userid = $student->id;
748         $gradeid = $DB->insert_record('assign_grades', $grade);
750         // We need to set the URL in order to view the feedback.
751         $PAGE->set_url('/a_url');
752         // A hack - these variables are used by the view_plugin_content function to
753         // determine what we actually want to view - would usually be set in URL.
754         global $_POST;
755         $_POST['plugin'] = 'comments';
756         $_POST['gid'] = $gradeid;
757         $_POST['sid'] = $submission->id;
759         // Trigger and capture the event.
760         $sink = $this->redirectEvents();
761         $assign->view('viewpluginassignfeedback');
762         $events = $sink->get_events();
763         $this->assertCount(1, $events);
764         $event = reset($events);
766         // Check that the event contains the expected values.
767         $this->assertInstanceOf('\mod_assign\event\feedback_viewed', $event);
768         $this->assertEquals($assign->get_context(), $event->get_context());
769         $this->assertEquals($gradeid, $event->objectid);
770         $expected = array(
771             $assign->get_course()->id,
772             'assign',
773             'view feedback',
774             'view.php?id=' . $assign->get_course_module()->id,
775             get_string('viewfeedbackforuser', 'assign', $student->id),
776             $assign->get_course_module()->id
777         );
778         $this->assertEventLegacyLogData($expected, $event);
779         $this->assertEventContextNotUsed($event);
780     }
782     /**
783      * Test the grading_form_viewed event.
784      */
785     public function test_grading_form_viewed() {
786         global $PAGE;
788         $this->resetAfterTest();
790         $course = $this->getDataGenerator()->create_course();
791         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
792         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
794         $this->setUser($teacher);
796         $assign = $this->create_instance($course);
798         // We need to set the URL in order to view the feedback.
799         $PAGE->set_url('/a_url');
800         // A hack - this variable is used by the view_single_grade_page function.
801         global $_POST;
802         $_POST['rownum'] = 1;
803         $_POST['userid'] = $student->id;
805         // Trigger and capture the event.
806         $sink = $this->redirectEvents();
807         $assign->view('grade');
808         $events = $sink->get_events();
809         $this->assertCount(1, $events);
810         $event = reset($events);
812         // Check that the event contains the expected values.
813         $this->assertInstanceOf('\mod_assign\event\grading_form_viewed', $event);
814         $this->assertEquals($assign->get_context(), $event->get_context());
815         $expected = array(
816             $assign->get_course()->id,
817             'assign',
818             'view grading form',
819             'view.php?id=' . $assign->get_course_module()->id,
820             get_string('viewgradingformforstudent', 'assign', array('id' => $student->id,
821                 'fullname' => fullname($student))),
822             $assign->get_course_module()->id
823         );
824         $this->assertEventLegacyLogData($expected, $event);
825         $this->assertEventContextNotUsed($event);
826     }
828     /**
829      * Test the grading_table_viewed event.
830      */
831     public function test_grading_table_viewed() {
832         global $PAGE;
834         $this->resetAfterTest();
836         $course = $this->getDataGenerator()->create_course();
837         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
838         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
840         $this->setUser($teacher);
842         $assign = $this->create_instance($course);
844         // We need to set the URL in order to view the feedback.
845         $PAGE->set_url('/a_url');
846         // A hack - this variable is used by the view_single_grade_page function.
847         global $_POST;
848         $_POST['rownum'] = 1;
849         $_POST['userid'] = $student->id;
851         // Trigger and capture the event.
852         $sink = $this->redirectEvents();
853         $assign->view('grading');
854         $events = $sink->get_events();
855         $this->assertCount(1, $events);
856         $event = reset($events);
858         // Check that the event contains the expected values.
859         $this->assertInstanceOf('\mod_assign\event\grading_table_viewed', $event);
860         $this->assertEquals($assign->get_context(), $event->get_context());
861         $expected = array(
862             $assign->get_course()->id,
863             'assign',
864             'view submission grading table',
865             'view.php?id=' . $assign->get_course_module()->id,
866             get_string('viewsubmissiongradingtable', 'assign'),
867             $assign->get_course_module()->id
868         );
869         $this->assertEventLegacyLogData($expected, $event);
870         $this->assertEventContextNotUsed($event);
871     }
873     /**
874      * Test the submission_form_viewed event.
875      */
876     public function test_submission_form_viewed() {
877         global $PAGE;
879         $this->resetAfterTest();
881         $course = $this->getDataGenerator()->create_course();
882         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
884         $this->setUser($student);
886         $assign = $this->create_instance($course);
888         // We need to set the URL in order to view the submission form.
889         $PAGE->set_url('/a_url');
891         // Trigger and capture the event.
892         $sink = $this->redirectEvents();
893         $assign->view('editsubmission');
894         $events = $sink->get_events();
895         $this->assertCount(1, $events);
896         $event = reset($events);
898         // Check that the event contains the expected values.
899         $this->assertInstanceOf('\mod_assign\event\submission_form_viewed', $event);
900         $this->assertEquals($assign->get_context(), $event->get_context());
901         $expected = array(
902             $assign->get_course()->id,
903             'assign',
904             'view submit assignment form',
905             'view.php?id=' . $assign->get_course_module()->id,
906             get_string('editsubmission', 'assign'),
907             $assign->get_course_module()->id
908         );
909         $this->assertEventLegacyLogData($expected, $event);
910         $this->assertEventContextNotUsed($event);
911     }
913     /**
914      * Test the submission_form_viewed event.
915      */
916     public function test_submission_confirmation_form_viewed() {
917         global $PAGE;
919         $this->resetAfterTest();
921         $course = $this->getDataGenerator()->create_course();
922         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
924         $this->setUser($student);
926         $assign = $this->create_instance($course);
928         // We need to set the URL in order to view the submission form.
929         $PAGE->set_url('/a_url');
931         // Trigger and capture the event.
932         $sink = $this->redirectEvents();
933         $assign->view('submit');
934         $events = $sink->get_events();
935         $this->assertCount(1, $events);
936         $event = reset($events);
938         // Check that the event contains the expected values.
939         $this->assertInstanceOf('\mod_assign\event\submission_confirmation_form_viewed', $event);
940         $this->assertEquals($assign->get_context(), $event->get_context());
941         $expected = array(
942             $assign->get_course()->id,
943             'assign',
944             'view confirm submit assignment form',
945             'view.php?id=' . $assign->get_course_module()->id,
946             get_string('viewownsubmissionform', 'assign'),
947             $assign->get_course_module()->id
948         );
949         $this->assertEventLegacyLogData($expected, $event);
950         $this->assertEventContextNotUsed($event);
951     }
953     /**
954      * Test the reveal_identities_confirmation_page_viewed event.
955      */
956     public function test_reveal_identities_confirmation_page_viewed() {
957         global $PAGE;
958         $this->resetAfterTest();
960         // Set to the admin user so we have the permission to reveal identities.
961         $this->setAdminUser();
963         $course = $this->getDataGenerator()->create_course();
964         $assign = $this->create_instance($course);
966         // We need to set the URL in order to view the submission form.
967         $PAGE->set_url('/a_url');
969         // Trigger and capture the event.
970         $sink = $this->redirectEvents();
971         $assign->view('revealidentities');
972         $events = $sink->get_events();
973         $this->assertCount(1, $events);
974         $event = reset($events);
976         // Check that the event contains the expected values.
977         $this->assertInstanceOf('\mod_assign\event\reveal_identities_confirmation_page_viewed', $event);
978         $this->assertEquals($assign->get_context(), $event->get_context());
979         $expected = array(
980             $assign->get_course()->id,
981             'assign',
982             'view',
983             'view.php?id=' . $assign->get_course_module()->id,
984             get_string('viewrevealidentitiesconfirm', 'assign'),
985             $assign->get_course_module()->id
986         );
987         $this->assertEventLegacyLogData($expected, $event);
988         $this->assertEventContextNotUsed($event);
989     }
991     /**
992      * Test the statement_accepted event.
993      */
994     public function test_statement_accepted() {
995         // We want to be a student so we can submit assignments.
996         $this->resetAfterTest();
998         $course = $this->getDataGenerator()->create_course();
999         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1001         $this->setUser($student);
1003         // We do not want to send any messages to the student during the PHPUNIT test.
1004         set_config('submissionreceipts', false, 'assign');
1006         $assign = $this->create_instance($course);
1008         // Create the data we want to pass to the submit_for_grading function.
1009         $data = new stdClass();
1010         $data->submissionstatement = 'We are the Borg. You will be assimilated. Resistance is futile. - do you agree
1011             to these terms?';
1013         // Trigger and capture the event.
1014         $sink = $this->redirectEvents();
1015         $assign->submit_for_grading($data, array());
1016         $events = $sink->get_events();
1017         $event = reset($events);
1019         // Check that the event contains the expected values.
1020         $this->assertInstanceOf('\mod_assign\event\statement_accepted', $event);
1021         $this->assertEquals($assign->get_context(), $event->get_context());
1022         $expected = array(
1023             $assign->get_course()->id,
1024             'assign',
1025             'submission statement accepted',
1026             'view.php?id=' . $assign->get_course_module()->id,
1027             get_string('submissionstatementacceptedlog',
1028                 'mod_assign',
1029                 fullname($student)),
1030             $assign->get_course_module()->id
1031         );
1032         $this->assertEventLegacyLogData($expected, $event);
1033         $this->assertEventContextNotUsed($event);
1035         // Enable the online text submission plugin.
1036         $submissionplugins = $assign->get_submission_plugins();
1037         foreach ($submissionplugins as $plugin) {
1038             if ($plugin->get_type() === 'onlinetext') {
1039                 $plugin->enable();
1040                 break;
1041             }
1042         }
1044         // Create the data we want to pass to the save_submission function.
1045         $data = new stdClass();
1046         $data->onlinetext_editor = array(
1047             'text' => 'Online text',
1048             'format' => FORMAT_HTML,
1049             'itemid' => file_get_unused_draft_itemid()
1050         );
1051         $data->submissionstatement = 'We are the Borg. You will be assimilated. Resistance is futile. - do you agree
1052             to these terms?';
1054         // Trigger and capture the event.
1055         $sink = $this->redirectEvents();
1056         $assign->save_submission($data, $notices);
1057         $events = $sink->get_events();
1058         $event = $events[2];
1060         // Check that the event contains the expected values.
1061         $this->assertInstanceOf('\mod_assign\event\statement_accepted', $event);
1062         $this->assertEquals($assign->get_context(), $event->get_context());
1063         $this->assertEventLegacyLogData($expected, $event);
1064         $this->assertEventContextNotUsed($event);
1065     }
1067     /**
1068      * Test the batch_set_workflow_state_viewed event.
1069      */
1070     public function test_batch_set_workflow_state_viewed() {
1071         $this->resetAfterTest();
1073         $course = $this->getDataGenerator()->create_course();
1074         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1075         $assign = $this->create_instance($course);
1077         // Trigger and capture the event.
1078         $sink = $this->redirectEvents();
1079         $assign->testable_view_batch_set_workflow_state($student->id);
1080         $events = $sink->get_events();
1081         $event = reset($events);
1083         // Check that the event contains the expected values.
1084         $this->assertInstanceOf('\mod_assign\event\batch_set_workflow_state_viewed', $event);
1085         $this->assertEquals($assign->get_context(), $event->get_context());
1086         $expected = array(
1087             $assign->get_course()->id,
1088             'assign',
1089             'view batch set marking workflow state',
1090             'view.php?id=' . $assign->get_course_module()->id,
1091             get_string('viewbatchsetmarkingworkflowstate', 'assign'),
1092             $assign->get_course_module()->id
1093         );
1094         $this->assertEventLegacyLogData($expected, $event);
1095         $this->assertEventContextNotUsed($event);
1096     }
1098     /**
1099      * Test the batch_set_marker_allocation_viewed event.
1100      */
1101     public function test_batch_set_marker_allocation_viewed() {
1102         $this->resetAfterTest();
1104         $course = $this->getDataGenerator()->create_course();
1105         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
1106         $assign = $this->create_instance($course);
1108         // Trigger and capture the event.
1109         $sink = $this->redirectEvents();
1110         $assign->testable_view_batch_markingallocation($student->id);
1111         $events = $sink->get_events();
1112         $event = reset($events);
1114         // Check that the event contains the expected values.
1115         $this->assertInstanceOf('\mod_assign\event\batch_set_marker_allocation_viewed', $event);
1116         $this->assertEquals($assign->get_context(), $event->get_context());
1117         $expected = array(
1118             $assign->get_course()->id,
1119             'assign',
1120             'view batch set marker allocation',
1121             'view.php?id=' . $assign->get_course_module()->id,
1122             get_string('viewbatchmarkingallocation', 'assign'),
1123             $assign->get_course_module()->id
1124         );
1125         $this->assertEventLegacyLogData($expected, $event);
1126         $this->assertEventContextNotUsed($event);
1127     }
1129     /**
1130      * Test the user override created event.
1131      *
1132      * There is no external API for creating a user override, so the unit test will simply
1133      * create and trigger the event and ensure the event data is returned as expected.
1134      */
1135     public function test_user_override_created() {
1136         $this->resetAfterTest();
1138         $course = $this->getDataGenerator()->create_course();
1139         $assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance(['course' => $course->id]);
1141         $params = array(
1142             'objectid' => 1,
1143             'relateduserid' => 2,
1144             'context' => context_module::instance($assign->cmid),
1145             'other' => array(
1146                 'assignid' => $assign->id
1147             )
1148         );
1149         $event = \mod_assign\event\user_override_created::create($params);
1151         // Trigger and capture the event.
1152         $sink = $this->redirectEvents();
1153         $event->trigger();
1154         $events = $sink->get_events();
1155         $event = reset($events);
1157         // Check that the event data is valid.
1158         $this->assertInstanceOf('\mod_assign\event\user_override_created', $event);
1159         $this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
1160         $this->assertEventContextNotUsed($event);
1161     }
1163     /**
1164      * Test the group override created event.
1165      *
1166      * There is no external API for creating a group override, so the unit test will simply
1167      * create and trigger the event and ensure the event data is returned as expected.
1168      */
1169     public function test_group_override_created() {
1170         $this->resetAfterTest();
1172         $course = $this->getDataGenerator()->create_course();
1173         $assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance(['course' => $course->id]);
1175         $params = array(
1176             'objectid' => 1,
1177             'context' => context_module::instance($assign->cmid),
1178             'other' => array(
1179                 'assignid' => $assign->id,
1180                 'groupid' => 2
1181             )
1182         );
1183         $event = \mod_assign\event\group_override_created::create($params);
1185         // Trigger and capture the event.
1186         $sink = $this->redirectEvents();
1187         $event->trigger();
1188         $events = $sink->get_events();
1189         $event = reset($events);
1191         // Check that the event data is valid.
1192         $this->assertInstanceOf('\mod_assign\event\group_override_created', $event);
1193         $this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
1194         $this->assertEventContextNotUsed($event);
1195     }
1197     /**
1198      * Test the user override updated event.
1199      *
1200      * There is no external API for updating a user override, so the unit test will simply
1201      * create and trigger the event and ensure the event data is returned as expected.
1202      */
1203     public function test_user_override_updated() {
1204         $this->resetAfterTest();
1206         $course = $this->getDataGenerator()->create_course();
1207         $assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance(['course' => $course->id]);
1209         $params = array(
1210             'objectid' => 1,
1211             'relateduserid' => 2,
1212             'context' => context_module::instance($assign->cmid),
1213             'other' => array(
1214                 'assignid' => $assign->id
1215             )
1216         );
1217         $event = \mod_assign\event\user_override_updated::create($params);
1219         // Trigger and capture the event.
1220         $sink = $this->redirectEvents();
1221         $event->trigger();
1222         $events = $sink->get_events();
1223         $event = reset($events);
1225         // Check that the event data is valid.
1226         $this->assertInstanceOf('\mod_assign\event\user_override_updated', $event);
1227         $this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
1228         $this->assertEventContextNotUsed($event);
1229     }
1231     /**
1232      * Test the group override updated event.
1233      *
1234      * There is no external API for updating a group override, so the unit test will simply
1235      * create and trigger the event and ensure the event data is returned as expected.
1236      */
1237     public function test_group_override_updated() {
1238         $this->resetAfterTest();
1240         $course = $this->getDataGenerator()->create_course();
1241         $assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance(['course' => $course->id]);
1243         $params = array(
1244             'objectid' => 1,
1245             'context' => context_module::instance($assign->cmid),
1246             'other' => array(
1247                 'assignid' => $assign->id,
1248                 'groupid' => 2
1249             )
1250         );
1251         $event = \mod_assign\event\group_override_updated::create($params);
1253         // Trigger and capture the event.
1254         $sink = $this->redirectEvents();
1255         $event->trigger();
1256         $events = $sink->get_events();
1257         $event = reset($events);
1259         // Check that the event data is valid.
1260         $this->assertInstanceOf('\mod_assign\event\group_override_updated', $event);
1261         $this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
1262         $this->assertEventContextNotUsed($event);
1263     }
1265     /**
1266      * Test the user override deleted event.
1267      */
1268     public function test_user_override_deleted() {
1269         global $DB;
1270         $this->resetAfterTest();
1272         $course = $this->getDataGenerator()->create_course();
1273         $assigninstance = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1274         $cm = get_coursemodule_from_instance('assign', $assigninstance->id, $course->id);
1275         $context = context_module::instance($cm->id);
1276         $assign = new assign($context, $cm, $course);
1278         // Create an override.
1279         $override = new stdClass();
1280         $override->assign = $assigninstance->id;
1281         $override->userid = 2;
1282         $override->id = $DB->insert_record('assign_overrides', $override);
1284         // Trigger and capture the event.
1285         $sink = $this->redirectEvents();
1286         $assign->delete_override($override->id);
1287         $events = $sink->get_events();
1288         $event = reset($events);
1290         // Check that the event data is valid.
1291         $this->assertInstanceOf('\mod_assign\event\user_override_deleted', $event);
1292         $this->assertEquals(context_module::instance($cm->id), $event->get_context());
1293         $this->assertEventContextNotUsed($event);
1294     }
1296     /**
1297      * Test the group override deleted event.
1298      */
1299     public function test_group_override_deleted() {
1300         global $DB;
1301         $this->resetAfterTest();
1303         $course = $this->getDataGenerator()->create_course();
1304         $assigninstance = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1305         $cm = get_coursemodule_from_instance('assign', $assigninstance->id, $course->id);
1306         $context = context_module::instance($cm->id);
1307         $assign = new assign($context, $cm, $course);
1309         // Create an override.
1310         $override = new stdClass();
1311         $override->assign = $assigninstance->id;
1312         $override->groupid = 2;
1313         $override->id = $DB->insert_record('assign_overrides', $override);
1315         // Trigger and capture the event.
1316         $sink = $this->redirectEvents();
1317         $assign->delete_override($override->id);
1318         $events = $sink->get_events();
1319         $event = reset($events);
1321         // Check that the event data is valid.
1322         $this->assertInstanceOf('\mod_assign\event\group_override_deleted', $event);
1323         $this->assertEquals(context_module::instance($cm->id), $event->get_context());
1324         $this->assertEventContextNotUsed($event);
1325     }