MDL-40697 mod_*: fixed unit tests so they pass
[moodle.git] / mod / quiz / 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  * Quiz events tests.
19  *
20  * @package    mod_quiz
21  * @category   phpunit
22  * @copyright  2013 Adrian Greeve
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
29 require_once($CFG->dirroot . '/mod/quiz/attemptlib.php');
31 /**
32  * Unit tests for quiz events.
33  *
34  * @package    mod_quiz
35  * @category   phpunit
36  * @copyright  2013 Adrian Greeve
37  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class mod_quiz_events_testcase extends advanced_testcase {
41     protected function prepare_quiz_data() {
43         $this->resetAfterTest(true);
45         // Create a course
46         $course = $this->getDataGenerator()->create_course();
48         // Make a quiz.
49         $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
51         $quiz = $quizgenerator->create_instance(array('course'=>$course->id, 'questionsperpage' => 0,
52             'grade' => 100.0, 'sumgrades' => 2));
54         $cm = get_coursemodule_from_instance('quiz', $quiz->id, $course->id);
56         // Create a couple of questions.
57         $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
59         $cat = $questiongenerator->create_question_category();
60         $saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
61         $numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
63         // Add them to the quiz.
64         quiz_add_quiz_question($saq->id, $quiz);
65         quiz_add_quiz_question($numq->id, $quiz);
67         // Make a user to do the quiz.
68         $user1 = $this->getDataGenerator()->create_user();
69         $this->setUser($user1);
71         $quizobj = quiz::create($quiz->id, $user1->id);
73         // Start the attempt.
74         $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
75         $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
77         $timenow = time();
78         $attempt = quiz_create_attempt($quizobj, 1, false, $timenow);
79         quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
80         quiz_attempt_save_started($quizobj, $quba, $attempt);
82         return array($quizobj, $quba, $attempt);
83     }
85     public function test_attempt_submitted() {
87         list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
88         $attemptobj = quiz_attempt::create($attempt->id);
90         // Catch the event.
91         $sink = $this->redirectEvents();
93         $timefinish = time();
94         $attemptobj->process_finish($timefinish, false);
95         $events = $sink->get_events();
96         $sink->close();
98         // Validate the event.
99         $this->assertCount(3, $events);
100         $event = $events[2];
101         $this->assertInstanceOf('\mod_quiz\event\attempt_submitted', $event);
102         $this->assertEquals('quiz_attempts', $event->objecttable);
103         $this->assertEquals($quizobj->get_context(), $event->get_context());
104         $this->assertEquals($attempt->userid, $event->relateduserid);
105         $this->assertEquals(null, $event->other['submitterid']); // Should be the user, but PHP Unit complains...
106         $this->assertEquals('quiz_attempt_submitted', $event->get_legacy_eventname());
107         $legacydata = new stdClass();
108         $legacydata->component = 'mod_quiz';
109         $legacydata->attemptid = (string) $attempt->id;
110         $legacydata->timestamp = $timefinish;
111         $legacydata->userid = $attempt->userid;
112         $legacydata->cmid = $quizobj->get_cmid();
113         $legacydata->courseid = $quizobj->get_courseid();
114         $legacydata->quizid = $quizobj->get_quizid();
115         // Submitterid should be the user, but as we are in PHP Unit, CLI_SCRIPT is set to true which sets null in submitterid.
116         $legacydata->submitterid = null;
117         $legacydata->timefinish = $timefinish;
118         $this->assertEventLegacyData($legacydata, $event);
119         $this->assertEventContextNotUsed($event);
120     }
122     public function test_attempt_becameoverdue() {
124         list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
125         $attemptobj = quiz_attempt::create($attempt->id);
127         // Catch the event.
128         $sink = $this->redirectEvents();
129         $timefinish = time();
130         $attemptobj->process_going_overdue($timefinish, false);
131         $events = $sink->get_events();
132         $sink->close();
134         $this->assertCount(1, $events);
135         $event = $events[0];
136         $this->assertInstanceOf('\mod_quiz\event\attempt_becameoverdue', $event);
137         $this->assertEquals('quiz_attempts', $event->objecttable);
138         $this->assertEquals($quizobj->get_context(), $event->get_context());
139         $this->assertEquals($attempt->userid, $event->relateduserid);
140         $this->assertNotEmpty($event->get_description());
141         // Submitterid should be the user, but as we are in PHP Unit, CLI_SCRIPT is set to true which sets null in submitterid.
142         $this->assertEquals(null, $event->other['submitterid']);
143         $this->assertEquals('quiz_attempt_overdue', $event->get_legacy_eventname());
144         $legacydata = new stdClass();
145         $legacydata->component = 'mod_quiz';
146         $legacydata->attemptid = (string) $attempt->id;
147         $legacydata->timestamp = $timefinish;
148         $legacydata->userid = $attempt->userid;
149         $legacydata->cmid = $quizobj->get_cmid();
150         $legacydata->courseid = $quizobj->get_courseid();
151         $legacydata->quizid = $quizobj->get_quizid();
152         $legacydata->submitterid = null; // Should be the user, but PHP Unit complains...
153         $this->assertEventLegacyData($legacydata, $event);
154         $this->assertEventContextNotUsed($event);
155     }
157     public function test_attempt_abandoned() {
159         list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
160         $attemptobj = quiz_attempt::create($attempt->id);
162         // Catch the event.
163         $sink = $this->redirectEvents();
164         $timefinish = time();
165         $attemptobj->process_abandon($timefinish, false);
166         $events = $sink->get_events();
167         $sink->close();
169         $this->assertCount(1, $events);
170         $event = $events[0];
171         $this->assertInstanceOf('\mod_quiz\event\attempt_abandoned', $event);
172         $this->assertEquals('quiz_attempts', $event->objecttable);
173         $this->assertEquals($quizobj->get_context(), $event->get_context());
174         $this->assertEquals($attempt->userid, $event->relateduserid);
175         // Submitterid should be the user, but as we are in PHP Unit, CLI_SCRIPT is set to true which sets null in submitterid.
176         $this->assertEquals(null, $event->other['submitterid']);
177         $this->assertEquals('quiz_attempt_abandoned', $event->get_legacy_eventname());
178         $legacydata = new stdClass();
179         $legacydata->component = 'mod_quiz';
180         $legacydata->attemptid = (string) $attempt->id;
181         $legacydata->timestamp = $timefinish;
182         $legacydata->userid = $attempt->userid;
183         $legacydata->cmid = $quizobj->get_cmid();
184         $legacydata->courseid = $quizobj->get_courseid();
185         $legacydata->quizid = $quizobj->get_quizid();
186         $legacydata->submitterid = null; // Should be the user, but PHP Unit complains...
187         $this->assertEventLegacyData($legacydata, $event);
188         $this->assertEventContextNotUsed($event);
189     }
191     public function test_attempt_started() {
192         list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
194         // Create another attempt.
195         $attempt = quiz_create_attempt($quizobj, 1, false, time(), false, 2);
197         // Trigger and capture the event.
198         $sink = $this->redirectEvents();
199         quiz_attempt_save_started($quizobj, $quba, $attempt);
200         $events = $sink->get_events();
201         $event = reset($events);
203         // Check that the event data is valid.
204         $this->assertInstanceOf('\mod_quiz\event\attempt_started', $event);
205         $this->assertEquals('quiz_attempts', $event->objecttable);
206         $this->assertEquals($attempt->id, $event->objectid);
207         $this->assertEquals($attempt->userid, $event->relateduserid);
208         $this->assertEquals($quizobj->get_context(), $event->get_context());
209         $this->assertEquals('quiz_attempt_started', $event->get_legacy_eventname());
210         $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
211         // Check legacy log data.
212         $expected = array($quizobj->get_courseid(), 'quiz', 'attempt', 'review.php?attempt=' . $attempt->id,
213             $quizobj->get_quizid(), $quizobj->get_cmid());
214         $this->assertEventLegacyLogData($expected, $event);
215         // Check legacy event data.
216         $legacydata = new stdClass();
217         $legacydata->component = 'mod_quiz';
218         $legacydata->attemptid = $attempt->id;
219         $legacydata->timestart = $attempt->timestart;
220         $legacydata->timestamp = $attempt->timestart;
221         $legacydata->userid = $attempt->userid;
222         $legacydata->quizid = $quizobj->get_quizid();
223         $legacydata->cmid = $quizobj->get_cmid();
224         $legacydata->courseid = $quizobj->get_courseid();
225         $this->assertEventLegacyData($legacydata, $event);
226         $this->assertEventContextNotUsed($event);
227     }
229     /**
230      * Test the edit page viewed event.
231      *
232      * There is no external API for updating a quiz, so the unit test will simply
233      * create and trigger the event and ensure the event data is returned as expected.
234      */
235     public function test_edit_page_viewed() {
236         $this->resetAfterTest();
238         $this->setAdminUser();
239         $course = $this->getDataGenerator()->create_course();
240         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
242         $params = array(
243             'courseid' => $course->id,
244             'context' => context_module::instance($quiz->cmid),
245             'other' => array(
246                 'quizid' => $quiz->id
247             )
248         );
249         $event = \mod_quiz\event\edit_page_viewed::create($params);
251         // Trigger and capture the event.
252         $sink = $this->redirectEvents();
253         $event->trigger();
254         $events = $sink->get_events();
255         $event = reset($events);
257         // Check that the event data is valid.
258         $this->assertInstanceOf('\mod_quiz\event\edit_page_viewed', $event);
259         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
260         $expected = array($course->id, 'quiz', 'editquestions', 'view.php?id=' . $quiz->cmid, $quiz->id, $quiz->cmid);
261         $this->assertEventLegacyLogData($expected, $event);
262         $this->assertEventContextNotUsed($event);
263     }
265     /**
266      * Test the attempt deleted event.
267      */
268     public function test_attempt_deleted() {
269         list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
271         // Trigger and capture the event.
272         $sink = $this->redirectEvents();
273         quiz_delete_attempt($attempt, $quizobj->get_quiz());
274         $events = $sink->get_events();
275         $event = reset($events);
277         // Check that the event data is valid.
278         $this->assertInstanceOf('\mod_quiz\event\attempt_deleted', $event);
279         $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
280         $expected = array($quizobj->get_courseid(), 'quiz', 'delete attempt', 'report.php?id=' . $quizobj->get_cmid(),
281             $attempt->id, $quizobj->get_cmid());
282         $this->assertEventLegacyLogData($expected, $event);
283         $this->assertEventContextNotUsed($event);
284     }
286     /**
287      * Test the report viewed event.
288      *
289      * There is no external API for viewing reports, so the unit test will simply
290      * create and trigger the event and ensure the event data is returned as expected.
291      */
292     public function test_report_viewed() {
293         $this->resetAfterTest();
295         $this->setAdminUser();
296         $course = $this->getDataGenerator()->create_course();
297         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
299         $params = array(
300             'context' => $context = context_module::instance($quiz->cmid),
301             'other' => array(
302                 'quizid' => $quiz->id,
303                 'reportname' => 'overview'
304             )
305         );
306         $event = \mod_quiz\event\report_viewed::create($params);
308         // Trigger and capture the event.
309         $sink = $this->redirectEvents();
310         $event->trigger();
311         $events = $sink->get_events();
312         $event = reset($events);
314         // Check that the event data is valid.
315         $this->assertInstanceOf('\mod_quiz\event\report_viewed', $event);
316         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
317         $expected = array($course->id, 'quiz', 'report', 'report.php?id=' . $quiz->cmid . '&mode=overview',
318             $quiz->id, $quiz->cmid);
319         $this->assertEventLegacyLogData($expected, $event);
320         $this->assertEventContextNotUsed($event);
321     }
323     /**
324      * Test the attempt reviewed event.
325      *
326      * There is no external API for reviewing attempts, so the unit test will simply
327      * create and trigger the event and ensure the event data is returned as expected.
328      */
329     public function test_attempt_reviewed() {
330         $this->resetAfterTest();
332         $this->setAdminUser();
333         $course = $this->getDataGenerator()->create_course();
334         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
336         $params = array(
337             'objectid' => 1,
338             'relateduserid' => 2,
339             'courseid' => $course->id,
340             'context' => context_module::instance($quiz->cmid),
341             'other' => array(
342                 'quizid' => $quiz->id
343             )
344         );
345         $event = \mod_quiz\event\attempt_reviewed::create($params);
347         // Trigger and capture the event.
348         $sink = $this->redirectEvents();
349         $event->trigger();
350         $events = $sink->get_events();
351         $event = reset($events);
353         // Check that the event data is valid.
354         $this->assertInstanceOf('\mod_quiz\event\attempt_reviewed', $event);
355         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
356         $expected = array($course->id, 'quiz', 'review', 'review.php?attempt=1', $quiz->id, $quiz->cmid);
357         $this->assertEventLegacyLogData($expected, $event);
358         $this->assertEventContextNotUsed($event);
359     }
361     /**
362      * Test the attempt summary viewed event.
363      *
364      * There is no external API for viewing the attempt summary, so the unit test will simply
365      * create and trigger the event and ensure the event data is returned as expected.
366      */
367     public function test_attempt_summary_viewed() {
368         $this->resetAfterTest();
370         $this->setAdminUser();
371         $course = $this->getDataGenerator()->create_course();
372         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
374         $params = array(
375             'objectid' => 1,
376             'relateduserid' => 2,
377             'courseid' => $course->id,
378             'context' => context_module::instance($quiz->cmid),
379             'other' => array(
380                 'quizid' => $quiz->id
381             )
382         );
383         $event = \mod_quiz\event\attempt_summary_viewed::create($params);
385         // Trigger and capture the event.
386         $sink = $this->redirectEvents();
387         $event->trigger();
388         $events = $sink->get_events();
389         $event = reset($events);
391         // Check that the event data is valid.
392         $this->assertInstanceOf('\mod_quiz\event\attempt_summary_viewed', $event);
393         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
394         $expected = array($course->id, 'quiz', 'view summary', 'summary.php?attempt=1', $quiz->id, $quiz->cmid);
395         $this->assertEventLegacyLogData($expected, $event);
396         $this->assertEventContextNotUsed($event);
397     }
399     /**
400      * Test the user override created event.
401      *
402      * There is no external API for creating a user override, so the unit test will simply
403      * create and trigger the event and ensure the event data is returned as expected.
404      */
405     public function test_user_override_created() {
406         $this->resetAfterTest();
408         $this->setAdminUser();
409         $course = $this->getDataGenerator()->create_course();
410         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
412         $params = array(
413             'objectid' => 1,
414             'relateduserid' => 2,
415             'context' => context_module::instance($quiz->cmid),
416             'other' => array(
417                 'quizid' => $quiz->id
418             )
419         );
420         $event = \mod_quiz\event\user_override_created::create($params);
422         // Trigger and capture the event.
423         $sink = $this->redirectEvents();
424         $event->trigger();
425         $events = $sink->get_events();
426         $event = reset($events);
428         // Check that the event data is valid.
429         $this->assertInstanceOf('\mod_quiz\event\user_override_created', $event);
430         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
431         $this->assertEventContextNotUsed($event);
432     }
434     /**
435      * Test the group override created event.
436      *
437      * There is no external API for creating a group override, so the unit test will simply
438      * create and trigger the event and ensure the event data is returned as expected.
439      */
440     public function test_group_override_created() {
441         $this->resetAfterTest();
443         $this->setAdminUser();
444         $course = $this->getDataGenerator()->create_course();
445         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
447         $params = array(
448             'objectid' => 1,
449             'context' => context_module::instance($quiz->cmid),
450             'other' => array(
451                 'quizid' => $quiz->id,
452                 'groupid' => 2
453             )
454         );
455         $event = \mod_quiz\event\group_override_created::create($params);
457         // Trigger and capture the event.
458         $sink = $this->redirectEvents();
459         $event->trigger();
460         $events = $sink->get_events();
461         $event = reset($events);
463         // Check that the event data is valid.
464         $this->assertInstanceOf('\mod_quiz\event\group_override_created', $event);
465         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
466         $this->assertEventContextNotUsed($event);
467     }
469     /**
470      * Test the user override updated event.
471      *
472      * There is no external API for updating a user override, so the unit test will simply
473      * create and trigger the event and ensure the event data is returned as expected.
474      */
475     public function test_user_override_updated() {
476         $this->resetAfterTest();
478         $this->setAdminUser();
479         $course = $this->getDataGenerator()->create_course();
480         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
482         $params = array(
483             'objectid' => 1,
484             'relateduserid' => 2,
485             'context' => context_module::instance($quiz->cmid),
486             'other' => array(
487                 'quizid' => $quiz->id
488             )
489         );
490         $event = \mod_quiz\event\user_override_updated::create($params);
492         // Trigger and capture the event.
493         $sink = $this->redirectEvents();
494         $event->trigger();
495         $events = $sink->get_events();
496         $event = reset($events);
498         // Check that the event data is valid.
499         $this->assertInstanceOf('\mod_quiz\event\user_override_updated', $event);
500         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
501         $expected = array($course->id, 'quiz', 'edit override', 'overrideedit.php?id=1', $quiz->id, $quiz->cmid);
502         $this->assertEventLegacyLogData($expected, $event);
503         $this->assertEventContextNotUsed($event);
504     }
506     /**
507      * Test the group override updated event.
508      *
509      * There is no external API for updating a group override, so the unit test will simply
510      * create and trigger the event and ensure the event data is returned as expected.
511      */
512     public function test_group_override_updated() {
513         $this->resetAfterTest();
515         $this->setAdminUser();
516         $course = $this->getDataGenerator()->create_course();
517         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
519         $params = array(
520             'objectid' => 1,
521             'context' => context_module::instance($quiz->cmid),
522             'other' => array(
523                 'quizid' => $quiz->id,
524                 'groupid' => 2
525             )
526         );
527         $event = \mod_quiz\event\group_override_updated::create($params);
529         // Trigger and capture the event.
530         $sink = $this->redirectEvents();
531         $event->trigger();
532         $events = $sink->get_events();
533         $event = reset($events);
535         // Check that the event data is valid.
536         $this->assertInstanceOf('\mod_quiz\event\group_override_updated', $event);
537         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
538         $expected = array($course->id, 'quiz', 'edit override', 'overrideedit.php?id=1', $quiz->id, $quiz->cmid);
539         $this->assertEventLegacyLogData($expected, $event);
540         $this->assertEventContextNotUsed($event);
541     }
543     /**
544      * Test the user override deleted event.
545      */
546     public function test_user_override_deleted() {
547         global $DB;
549         $this->resetAfterTest();
551         $this->setAdminUser();
552         $course = $this->getDataGenerator()->create_course();
553         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
555         // Create an override.
556         $override = new stdClass();
557         $override->quiz = $quiz->id;
558         $override->userid = 2;
559         $override->id = $DB->insert_record('quiz_overrides', $override);
561         // Trigger and capture the event.
562         $sink = $this->redirectEvents();
563         quiz_delete_override($quiz, $override->id);
564         $events = $sink->get_events();
565         $event = reset($events);
567         // Check that the event data is valid.
568         $this->assertInstanceOf('\mod_quiz\event\user_override_deleted', $event);
569         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
570         $expected = array($course->id, 'quiz', 'delete override', 'overrides.php?cmid=' . $quiz->cmid, $quiz->id, $quiz->cmid);
571         $this->assertEventLegacyLogData($expected, $event);
572         $this->assertEventContextNotUsed($event);
573     }
575     /**
576      * Test the group override deleted event.
577      */
578     public function test_group_override_deleted() {
579         global $DB;
581         $this->resetAfterTest();
583         $this->setAdminUser();
584         $course = $this->getDataGenerator()->create_course();
585         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
587         // Create an override.
588         $override = new stdClass();
589         $override->quiz = $quiz->id;
590         $override->groupid = 2;
591         $override->id = $DB->insert_record('quiz_overrides', $override);
593         // Trigger and capture the event.
594         $sink = $this->redirectEvents();
595         quiz_delete_override($quiz, $override->id);
596         $events = $sink->get_events();
597         $event = reset($events);
599         // Check that the event data is valid.
600         $this->assertInstanceOf('\mod_quiz\event\group_override_deleted', $event);
601         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
602         $expected = array($course->id, 'quiz', 'delete override', 'overrides.php?cmid=' . $quiz->cmid, $quiz->id, $quiz->cmid);
603         $this->assertEventLegacyLogData($expected, $event);
604         $this->assertEventContextNotUsed($event);
605     }
607     /**
608      * Test the attempt viewed event.
609      *
610      * There is no external API for continuing an attempt, so the unit test will simply
611      * create and trigger the event and ensure the event data is returned as expected.
612      */
613     public function test_attempt_viewed() {
614         $this->resetAfterTest();
616         $this->setAdminUser();
617         $course = $this->getDataGenerator()->create_course();
618         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
620         $params = array(
621             'objectid' => 1,
622             'relateduserid' => 2,
623             'courseid' => $course->id,
624             'context' => context_module::instance($quiz->cmid),
625             'other' => array(
626                 'quizid' => $quiz->id
627             )
628         );
629         $event = \mod_quiz\event\attempt_viewed::create($params);
631         // Trigger and capture the event.
632         $sink = $this->redirectEvents();
633         $event->trigger();
634         $events = $sink->get_events();
635         $event = reset($events);
637         // Check that the event data is valid.
638         $this->assertInstanceOf('\mod_quiz\event\attempt_viewed', $event);
639         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
640         $expected = array($course->id, 'quiz', 'continue attempt', 'review.php?attempt=1', $quiz->id, $quiz->cmid);
641         $this->assertEventLegacyLogData($expected, $event);
642         $this->assertEventContextNotUsed($event);
643     }
645     /**
646      * Test the attempt previewed event.
647      */
648     public function test_attempt_preview_started() {
649         list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
651         // We want to preview this attempt.
652         $attempt = quiz_create_attempt($quizobj, 1, false, time(), false, 2);
653         $attempt->preview = 1;
655         // Trigger and capture the event.
656         $sink = $this->redirectEvents();
657         quiz_attempt_save_started($quizobj, $quba, $attempt);
658         $events = $sink->get_events();
659         $event = reset($events);
661         // Check that the event data is valid.
662         $this->assertInstanceOf('\mod_quiz\event\attempt_preview_started', $event);
663         $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
664         $expected = array($quizobj->get_courseid(), 'quiz', 'preview', 'view.php?id=' . $quizobj->get_cmid(),
665             $quizobj->get_quizid(), $quizobj->get_cmid());
666         $this->assertEventLegacyLogData($expected, $event);
667         $this->assertEventContextNotUsed($event);
668     }
670     /**
671      * Test the question manually graded event.
672      *
673      * There is no external API for manually grading a question, so the unit test will simply
674      * create and trigger the event and ensure the event data is returned as expected.
675      */
676     public function test_question_manually_graded() {
677         list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
679         $params = array(
680             'objectid' => 1,
681             'courseid' => $quizobj->get_courseid(),
682             'context' => context_module::instance($quizobj->get_cmid()),
683             'other' => array(
684                 'quizid' => $quizobj->get_quizid(),
685                 'attemptid' => 2,
686                 'slot' => 3
687             )
688         );
689         $event = \mod_quiz\event\question_manually_graded::create($params);
691         // Trigger and capture the event.
692         $sink = $this->redirectEvents();
693         $event->trigger();
694         $events = $sink->get_events();
695         $event = reset($events);
697         // Check that the event data is valid.
698         $this->assertInstanceOf('\mod_quiz\event\question_manually_graded', $event);
699         $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
700         $expected = array($quizobj->get_courseid(), 'quiz', 'manualgrade', 'comment.php?attempt=2&slot=3',
701             $quizobj->get_quizid(), $quizobj->get_cmid());
702         $this->assertEventLegacyLogData($expected, $event);
703         $this->assertEventContextNotUsed($event);
704     }