MDL-41101 mod_assign: replaced 'view feedback' add_to_log call with an event
[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/base_test.php');
29 require_once($CFG->dirroot . '/mod/assign/tests/fixtures/event_mod_assign_fixtures.php');
31 /**
32  * Contains the event tests for the module assign.
33  *
34  * @package   mod_assign
35  * @copyright 2014 Adrian Greeve <adrian@moodle.com>
36  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class assign_events_testcase extends mod_assign_base_testcase {
40     /**
41      * Basic tests for the submission_created() abstract class.
42      */
43     public function test_submission_created() {
44         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
45         $instance = $generator->create_instance(array('course' => $this->course->id));
46         $modcontext = context_module::instance($instance->cmid);
48         // Standard Event parameters.
49         $params = array(
50             'context' => $modcontext,
51             'courseid' => $this->course->id
52         );
54         $eventinfo = $params;
55         $eventinfo['other'] = array(
56             'submissionid' => '17',
57             'submissionattempt' => 0,
58             'submissionstatus' => 'submitted'
59         );
61         $sink = $this->redirectEvents();
62         $event = \mod_assign_unittests\event\submission_created::create($eventinfo);
63         $event->trigger();
64         $result = $sink->get_events();
65         $event = reset($result);
66         $sink->close();
68         $this->assertEquals($modcontext->id, $event->contextid);
69         $this->assertEquals($this->course->id, $event->courseid);
71         // Check that an error occurs when teamsubmission is not set.
72         try {
73             \mod_assign_unittests\event\submission_created::create($params);
74             $this->fail('Other must contain the key submissionid.');
75         } catch (Exception $e) {
76             $this->assertInstanceOf('coding_exception', $e);
77         }
78         // Check that the submission status debugging is fired.
79         $subinfo = $params;
80         $subinfo['other'] = array('submissionid' => '23');
81         try {
82             \mod_assign_unittests\event\submission_created::create($subinfo);
83             $this->fail('Other must contain the key submissionattempt.');
84         } catch (Exception $e) {
85             $this->assertInstanceOf('coding_exception', $e);
86         }
88         $subinfo['other'] = array('submissionattempt' => '0');
89         try {
90             \mod_assign_unittests\event\submission_created::create($subinfo);
91             $this->fail('Other must contain the key submissionstatus.');
92         } catch (Exception $e) {
93             $this->assertInstanceOf('coding_exception', $e);
94         }
95     }
97     /**
98      * Basic tests for the submission_updated() abstract class.
99      */
100     public function test_submission_updated() {
101         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
102         $instance = $generator->create_instance(array('course' => $this->course->id));
103         $modcontext = context_module::instance($instance->cmid);
105         // Standard Event parameters.
106         $params = array(
107             'context' => $modcontext,
108             'courseid' => $this->course->id
109         );
111         $eventinfo = $params;
112         $eventinfo['other'] = array(
113             'submissionid' => '17',
114             'submissionattempt' => 0,
115             'submissionstatus' => 'submitted'
116         );
118         $sink = $this->redirectEvents();
119         $event = \mod_assign_unittests\event\submission_updated::create($eventinfo);
120         $event->trigger();
121         $result = $sink->get_events();
122         $event = reset($result);
123         $sink->close();
125         $this->assertEquals($modcontext->id, $event->contextid);
126         $this->assertEquals($this->course->id, $event->courseid);
128         // Check that an error occurs when teamsubmission is not set.
129         try {
130             \mod_assign_unittests\event\submission_created::create($params);
131             $this->fail('Other must contain the key submissionid.');
132         } catch (Exception $e) {
133             $this->assertInstanceOf('coding_exception', $e);
134         }
135         // Check that the submission status debugging is fired.
136         $subinfo = $params;
137         $subinfo['other'] = array('submissionid' => '23');
138         try {
139             \mod_assign_unittests\event\submission_created::create($subinfo);
140             $this->fail('Other must contain the key submissionattempt.');
141         } catch (Exception $e) {
142             $this->assertInstanceOf('coding_exception', $e);
143         }
145         $subinfo['other'] = array('submissionattempt' => '0');
146         try {
147             \mod_assign_unittests\event\submission_created::create($subinfo);
148             $this->fail('Other must contain the key submissionstatus.');
149         } catch (Exception $e) {
150             $this->assertInstanceOf('coding_exception', $e);
151         }
152     }
154     public function test_extension_granted() {
155         $this->setUser($this->editingteachers[0]);
157         $tomorrow = time() + 24*60*60;
158         $yesterday = time() - 24*60*60;
160         $assign = $this->create_instance(array('duedate' => $yesterday, 'cutoffdate' => $yesterday));
161         $sink = $this->redirectEvents();
163         $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
165         $events = $sink->get_events();
166         $this->assertCount(1, $events);
167         $event = reset($events);
168         $this->assertInstanceOf('\mod_assign\event\extension_granted', $event);
169         $this->assertEquals($assign->get_context(), $event->get_context());
170         $this->assertEquals($assign->get_instance()->id, $event->objectid);
171         $this->assertEquals($this->students[0]->id, $event->relateduserid);
172         $expected = array(
173             $assign->get_course()->id,
174             'assign',
175             'grant extension',
176             'view.php?id=' . $assign->get_course_module()->id,
177             $this->students[0]->id,
178             $assign->get_course_module()->id
179         );
180         $this->assertEventLegacyLogData($expected, $event);
181         $sink->close();
182     }
184     public function test_submission_locked() {
185         $this->editingteachers[0]->ignoresesskey = true;
186         $this->setUser($this->editingteachers[0]);
188         $assign = $this->create_instance();
189         $sink = $this->redirectEvents();
191         $assign->lock_submission($this->students[0]->id);
193         $events = $sink->get_events();
194         $this->assertCount(1, $events);
195         $event = reset($events);
196         $this->assertInstanceOf('\mod_assign\event\submission_locked', $event);
197         $this->assertEquals($assign->get_context(), $event->get_context());
198         $this->assertEquals($assign->get_instance()->id, $event->objectid);
199         $this->assertEquals($this->students[0]->id, $event->relateduserid);
200         $expected = array(
201             $assign->get_course()->id,
202             'assign',
203             'lock submission',
204             'view.php?id=' . $assign->get_course_module()->id,
205             get_string('locksubmissionforstudent', 'assign', array('id' => $this->students[0]->id,
206                 'fullname' => fullname($this->students[0]))),
207             $assign->get_course_module()->id
208         );
209         $this->assertEventLegacyLogData($expected, $event);
210         $sink->close();
212         // Revert to defaults.
213         $this->editingteachers[0]->ignoresesskey = false;
214     }
216     public function test_identities_revealed() {
217         $this->editingteachers[0]->ignoresesskey = true;
218         $this->setUser($this->editingteachers[0]);
220         $assign = $this->create_instance(array('blindmarking'=>1));
221         $sink = $this->redirectEvents();
223         $assign->reveal_identities();
225         $events = $sink->get_events();
226         $this->assertCount(1, $events);
227         $event = reset($events);
228         $this->assertInstanceOf('\mod_assign\event\identities_revealed', $event);
229         $this->assertEquals($assign->get_context(), $event->get_context());
230         $this->assertEquals($assign->get_instance()->id, $event->objectid);
231         $expected = array(
232             $assign->get_course()->id,
233             'assign',
234             'reveal identities',
235             'view.php?id=' . $assign->get_course_module()->id,
236             get_string('revealidentities', 'assign'),
237             $assign->get_course_module()->id
238         );
239         $this->assertEventLegacyLogData($expected, $event);
240         $sink->close();
242         // Revert to defaults.
243         $this->editingteachers[0]->ignoresesskey = false;
244     }
246     public function test_submission_status_updated() {
247         $this->editingteachers[0]->ignoresesskey = true;
248         $this->setUser($this->editingteachers[0]);
250         $assign = $this->create_instance();
251         $submission = $assign->get_user_submission($this->students[0]->id, true);
252         $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
253         $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
255         $sink = $this->redirectEvents();
256         $assign->revert_to_draft($this->students[0]->id);
258         $events = $sink->get_events();
259         $this->assertCount(1, $events);
260         $event = reset($events);
261         $this->assertInstanceOf('\mod_assign\event\submission_status_updated', $event);
262         $this->assertEquals($assign->get_context(), $event->get_context());
263         $this->assertEquals($submission->id, $event->objectid);
264         $this->assertEquals($this->students[0]->id, $event->relateduserid);
265         $this->assertEquals(ASSIGN_SUBMISSION_STATUS_DRAFT, $event->other['newstatus']);
266         $expected = array(
267             $assign->get_course()->id,
268             'assign',
269             'revert submission to draft',
270             'view.php?id=' . $assign->get_course_module()->id,
271             get_string('reverttodraftforstudent', 'assign', array('id' => $this->students[0]->id,
272                 'fullname' => fullname($this->students[0]))),
273             $assign->get_course_module()->id
274         );
275         $this->assertEventLegacyLogData($expected, $event);
276         $sink->close();
278         // Revert to defaults.
279         $this->editingteachers[0]->ignoresesskey = false;
280     }
282     public function test_marker_updated() {
283         $this->editingteachers[0]->ignoresesskey = true;
284         $this->setUser($this->editingteachers[0]);
286         $assign = $this->create_instance();
288         $sink = $this->redirectEvents();
289         $assign->testable_process_set_batch_marking_allocation($this->students[0]->id, $this->teachers[0]->id);
291         $events = $sink->get_events();
292         $this->assertCount(1, $events);
293         $event = reset($events);
294         $this->assertInstanceOf('\mod_assign\event\marker_updated', $event);
295         $this->assertEquals($assign->get_context(), $event->get_context());
296         $this->assertEquals($assign->get_instance()->id, $event->objectid);
297         $this->assertEquals($this->students[0]->id, $event->relateduserid);
298         $this->assertEquals($this->editingteachers[0]->id, $event->userid);
299         $this->assertEquals($this->teachers[0]->id, $event->other['markerid']);
300         $expected = array(
301             $assign->get_course()->id,
302             'assign',
303             'set marking allocation',
304             'view.php?id=' . $assign->get_course_module()->id,
305             get_string('setmarkerallocationforlog', 'assign', array('id' => $this->students[0]->id,
306                 'fullname' => fullname($this->students[0]), 'marker' => fullname($this->teachers[0]))),
307             $assign->get_course_module()->id
308         );
309         $this->assertEventLegacyLogData($expected, $event);
310         $sink->close();
312         // Revert to defaults.
313         $this->editingteachers[0]->ignoresesskey = false;
314     }
316     public function test_workflow_state_updated() {
317         $this->editingteachers[0]->ignoresesskey = true;
318         $this->setUser($this->editingteachers[0]);
320         $assign = $this->create_instance();
322         $sink = $this->redirectEvents();
323         $assign->testable_process_set_batch_marking_workflow_state($this->students[0]->id, ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW);
325         $events = $sink->get_events();
326         $this->assertCount(1, $events);
327         $event = reset($events);
328         $this->assertInstanceOf('\mod_assign\event\workflow_state_updated', $event);
329         $this->assertEquals($assign->get_context(), $event->get_context());
330         $this->assertEquals($assign->get_instance()->id, $event->objectid);
331         $this->assertEquals($this->students[0]->id, $event->relateduserid);
332         $this->assertEquals($this->editingteachers[0]->id, $event->userid);
333         $this->assertEquals(ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW, $event->other['newstate']);
334         $expected = array(
335             $assign->get_course()->id,
336             'assign',
337             'set marking workflow state',
338             'view.php?id=' . $assign->get_course_module()->id,
339             get_string('setmarkingworkflowstateforlog', 'assign', array('id' => $this->students[0]->id,
340                 'fullname' => fullname($this->students[0]), 'state' => ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW)),
341             $assign->get_course_module()->id
342         );
343         $this->assertEventLegacyLogData($expected, $event);
344         $sink->close();
346         // Revert to defaults.
347         $this->editingteachers[0]->ignoresesskey = false;
348     }
350     public function test_submission_duplicated() {
351         $this->setUser($this->students[0]);
353         $assign = $this->create_instance();
354         $submission1 = $assign->get_user_submission($this->students[0]->id, true, 0);
355         $submission2 = $assign->get_user_submission($this->students[0]->id, true, 1);
356         $submission2->status = ASSIGN_SUBMISSION_STATUS_REOPENED;
357         $assign->testable_update_submission($submission2, $this->students[0]->id, time(), $assign->get_instance()->teamsubmission);
359         $sink = $this->redirectEvents();
360         $notices = null;
361         $assign->copy_previous_attempt($notices);
363         $events = $sink->get_events();
364         $this->assertCount(1, $events);
365         $event = reset($events);
366         $this->assertInstanceOf('\mod_assign\event\submission_duplicated', $event);
367         $this->assertEquals($assign->get_context(), $event->get_context());
368         $this->assertEquals($submission2->id, $event->objectid);
369         $this->assertEquals($this->students[0]->id, $event->userid);
370         $submission2->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
371         $expected = array(
372             $assign->get_course()->id,
373             'assign',
374             'submissioncopied',
375             'view.php?id=' . $assign->get_course_module()->id,
376             $assign->testable_format_submission_for_log($submission2),
377             $assign->get_course_module()->id
378         );
379         $this->assertEventLegacyLogData($expected, $event);
380         $sink->close();
381     }
383     public function test_submission_unlocked() {
384         $this->editingteachers[0]->ignoresesskey = true;
385         $this->setUser($this->editingteachers[0]);
387         $assign = $this->create_instance();
388         $sink = $this->redirectEvents();
390         $assign->unlock_submission($this->students[0]->id);
392         $events = $sink->get_events();
393         $this->assertCount(1, $events);
394         $event = reset($events);
395         $this->assertInstanceOf('\mod_assign\event\submission_unlocked', $event);
396         $this->assertEquals($assign->get_context(), $event->get_context());
397         $this->assertEquals($assign->get_instance()->id, $event->objectid);
398         $this->assertEquals($this->students[0]->id, $event->relateduserid);
399         $expected = array(
400             $assign->get_course()->id,
401             'assign',
402             'unlock submission',
403             'view.php?id=' . $assign->get_course_module()->id,
404             get_string('unlocksubmissionforstudent', 'assign', array('id' => $this->students[0]->id,
405                 'fullname' => fullname($this->students[0]))),
406             $assign->get_course_module()->id
407         );
408         $this->assertEventLegacyLogData($expected, $event);
409         $sink->close();
411         // Revert to defaults.
412         $this->editingteachers[0]->ignoresesskey = false;
413     }
415     public function test_submission_graded() {
416         $this->setUser($this->editingteachers[0]);
417         $assign = $this->create_instance();
419         // Test apply_grade_to_user.
420         $sink = $this->redirectEvents();
422         $data = new stdClass();
423         $data->grade = '50.0';
424         $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
425         $grade = $assign->get_user_grade($this->students[0]->id, false, 0);
427         $events = $sink->get_events();
428         $this->assertCount(1, $events);
429         $event = reset($events);
430         $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
431         $this->assertEquals($assign->get_context(), $event->get_context());
432         $this->assertEquals($grade->id, $event->objectid);
433         $this->assertEquals($this->students[0]->id, $event->relateduserid);
434         $expected = array(
435             $assign->get_course()->id,
436             'assign',
437             'grade submission',
438             'view.php?id=' . $assign->get_course_module()->id,
439             $assign->format_grade_for_log($grade),
440             $assign->get_course_module()->id
441         );
442         $this->assertEventLegacyLogData($expected, $event);
443         $sink->close();
445         // Test process_save_quick_grades.
446         $sink = $this->redirectEvents();
448         $data = array(
449             'grademodified_' . $this->students[0]->id => time(),
450             'quickgrade_' . $this->students[0]->id => '60.0'
451         );
452         $assign->testable_process_save_quick_grades($data);
453         $grade = $assign->get_user_grade($this->students[0]->id, false);
454         $this->assertEquals('60.0', $grade->grade);
456         $events = $sink->get_events();
457         $this->assertCount(1, $events);
458         $event = reset($events);
459         $this->assertInstanceOf('\mod_assign\event\submission_graded', $event);
460         $this->assertEquals($assign->get_context(), $event->get_context());
461         $this->assertEquals($grade->id, $event->objectid);
462         $this->assertEquals($this->students[0]->id, $event->relateduserid);
463         $expected = array(
464             $assign->get_course()->id,
465             'assign',
466             'grade submission',
467             'view.php?id=' . $assign->get_course_module()->id,
468             $assign->format_grade_for_log($grade),
469             $assign->get_course_module()->id
470         );
471         $this->assertEventLegacyLogData($expected, $event);
472         $sink->close();
473     }
475     /**
476      * Test the submission_viewed event.
477      */
478     public function test_submission_viewed() {
479         global $PAGE;
481         $this->setUser($this->editingteachers[0]);
483         $assign = $this->create_instance();
484         $submission = $assign->get_user_submission($this->students[0]->id, true);
486         // We need to set the URL in order to view the submission.
487         $PAGE->set_url('/a_url');
488         // A hack - these variables are used by the view_plugin_content function to
489         // determine what we actually want to view - would usually be set in URL.
490         global $_POST;
491         $_POST['plugin'] = 'comments';
492         $_POST['sid'] = $submission->id;
494         // Trigger and capture the event.
495         $sink = $this->redirectEvents();
496         $assign->view('viewpluginassignsubmission');
497         $events = $sink->get_events();
498         $this->assertCount(1, $events);
499         $event = reset($events);
501         // Check that the event contains the expected values.
502         $this->assertInstanceOf('\mod_assign\event\submission_viewed', $event);
503         $this->assertEquals($assign->get_context(), $event->get_context());
504         $this->assertEquals($submission->id, $event->objectid);
505         $expected = array(
506             $assign->get_course()->id,
507             'assign',
508             'view submission',
509             'view.php?id=' . $assign->get_course_module()->id,
510             get_string('viewsubmissionforuser', 'assign', $this->students[0]->id),
511             $assign->get_course_module()->id
512         );
513         $this->assertEventLegacyLogData($expected, $event);
514         $this->assertEventContextNotUsed($event);
515     }
517     /**
518      * Test the feedback_viewed event.
519      */
520     public function test_feedback_viewed() {
521         global $DB, $PAGE;
523         $this->setUser($this->editingteachers[0]);
525         $assign = $this->create_instance();
526         $submission = $assign->get_user_submission($this->students[0]->id, true);
528         // Insert a grade for this submission.
529         $grade = new stdClass();
530         $grade->assignment = 1;
531         $grade->userid = $this->students[0]->id;
532         $gradeid = $DB->insert_record('assign_grades', $grade);
534         // We need to set the URL in order to view the feedback.
535         $PAGE->set_url('/a_url');
536         // A hack - these variables are used by the view_plugin_content function to
537         // determine what we actually want to view - would usually be set in URL.
538         global $_POST;
539         $_POST['plugin'] = 'comments';
540         $_POST['gid'] = $gradeid;
541         $_POST['sid'] = $submission->id;
543         // Trigger and capture the event.
544         $sink = $this->redirectEvents();
545         $assign->view('viewpluginassignfeedback');
546         $events = $sink->get_events();
547         $this->assertCount(1, $events);
548         $event = reset($events);
550         // Check that the event contains the expected values.
551         $this->assertInstanceOf('\mod_assign\event\feedback_viewed', $event);
552         $this->assertEquals($assign->get_context(), $event->get_context());
553         $this->assertEquals($gradeid, $event->objectid);
554         $expected = array(
555             $assign->get_course()->id,
556             'assign',
557             'view feedback',
558             'view.php?id=' . $assign->get_course_module()->id,
559             get_string('viewfeedbackforuser', 'assign', $this->students[0]->id),
560             $assign->get_course_module()->id
561         );
562         $this->assertEventLegacyLogData($expected, $event);
563         $this->assertEventContextNotUsed($event);
564     }