MDL-60826 calendar: further performance improvements
[moodle.git] / mod / assign / tests / events_test.php
blob8dfd76885ceb2cfbc7b8e914391fab9de4075cad
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.
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.
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
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.
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
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.
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,
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);
70 /**
71 * Basic tests for the submission_created() abstract class.
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
87 $eventinfo = $params;
88 $eventinfo['other'] = array(
89 'submissionid' => '17',
90 'submissionattempt' => 0,
91 'submissionstatus' => 'submitted'
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);
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);
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);
131 * Basic tests for the submission_updated() abstract class.
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
147 $eventinfo = $params;
148 $eventinfo['other'] = array(
149 'submissionid' => '17',
150 'submissionattempt' => 0,
151 'submissionstatus' => 'submitted'
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);
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);
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);
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,
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
227 $this->assertEventLegacyLogData($expected, $event);
228 $sink->close();
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
262 $this->assertEventLegacyLogData($expected, $event);
263 $sink->close();
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
294 $this->assertEventLegacyLogData($expected, $event);
295 $sink->close();
299 * Test the submission_status_viewed event.
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
333 $this->assertEventLegacyLogData($expected, $event);
334 $this->assertEventContextNotUsed($event);
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
371 $this->assertEventLegacyLogData($expected, $event);
372 $sink->close();
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
408 $this->assertEventLegacyLogData($expected, $event);
409 $sink->close();
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
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
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'
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
506 $this->assertEventLegacyLogData($expected, $event);
507 $sink->close();
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
544 $this->assertEventLegacyLogData($expected, $event);
545 $sink->close();
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
579 $this->assertEventLegacyLogData($expected, $event);
580 $sink->close();
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
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'
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
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
675 $this->assertEventLegacyLogData($expected, $event);
676 $sink->close();
680 * Test the submission_viewed event.
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
723 $this->assertEventLegacyLogData($expected, $event);
724 $this->assertEventContextNotUsed($event);
728 * Test the feedback_viewed event.
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
778 $this->assertEventLegacyLogData($expected, $event);
779 $this->assertEventContextNotUsed($event);
783 * Test the grading_form_viewed event.
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
824 $this->assertEventLegacyLogData($expected, $event);
825 $this->assertEventContextNotUsed($event);
829 * Test the grading_table_viewed event.
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
869 $this->assertEventLegacyLogData($expected, $event);
870 $this->assertEventContextNotUsed($event);
874 * Test the submission_form_viewed event.
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
909 $this->assertEventLegacyLogData($expected, $event);
910 $this->assertEventContextNotUsed($event);
914 * Test the submission_form_viewed event.
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
949 $this->assertEventLegacyLogData($expected, $event);
950 $this->assertEventContextNotUsed($event);
954 * Test the reveal_identities_confirmation_page_viewed event.
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
987 $this->assertEventLegacyLogData($expected, $event);
988 $this->assertEventContextNotUsed($event);
992 * Test the statement_accepted event.
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
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;
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()
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);
1068 * Test the batch_set_workflow_state_viewed event.
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
1094 $this->assertEventLegacyLogData($expected, $event);
1095 $this->assertEventContextNotUsed($event);
1099 * Test the batch_set_marker_allocation_viewed event.
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
1125 $this->assertEventLegacyLogData($expected, $event);
1126 $this->assertEventContextNotUsed($event);
1130 * Test the user override created event.
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.
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
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);
1164 * Test the group override created event.
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.
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
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);
1198 * Test the user override updated event.
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.
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
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);
1232 * Test the group override updated event.
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.
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
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);
1266 * Test the user override deleted event.
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);
1297 * Test the group override deleted event.
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);