Proyectos de Subversion Moodle

Rev

Rev 11 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * 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
 */
25
 
26
namespace mod_quiz\event;
27
 
28
use mod_quiz\quiz_attempt;
29
use mod_quiz\quiz_settings;
30
use context_module;
1441 ariadna 31
use mod_quiz\external\submit_question_version;
1 efrain 32
 
33
/**
34
 * Unit tests for quiz events.
35
 *
36
 * @package    mod_quiz
37
 * @category   phpunit
38
 * @copyright  2013 Adrian Greeve
39
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1441 ariadna 40
 * @covers \mod_quiz\external\submit_question_version
1 efrain 41
 */
1441 ariadna 42
final class events_test extends \advanced_testcase {
1 efrain 43
 
44
    /**
45
     * Set up a quiz.
46
     *
47
     * The quiz contains two questions, a short-answer one and a numerical one.
48
     *
49
     * @return quiz_settings the generated quiz.
50
     */
51
    protected function prepare_quiz() {
52
 
53
        $this->resetAfterTest(true);
54
 
55
        // Create a course
56
        $course = $this->getDataGenerator()->create_course();
57
 
58
        // Make a quiz.
59
        $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
60
 
61
        $quiz = $quizgenerator->create_instance(['course' => $course->id, 'questionsperpage' => 0,
62
                'grade' => 100.0, 'sumgrades' => 2]);
63
 
64
        get_coursemodule_from_instance('quiz', $quiz->id, $course->id);
65
 
66
        // Create a couple of questions.
67
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
68
 
69
        $cat = $questiongenerator->create_question_category();
70
        $saq = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
71
        $numq = $questiongenerator->create_question('numerical', null, ['category' => $cat->id]);
72
 
1441 ariadna 73
        // Update the numq question so it has multiple versions. Needed to test
74
        // the version updated event.
75
        $questiongenerator->update_question($numq, null, ['name' => 'Second version of numq']);
76
 
1 efrain 77
        // Add them to the quiz.
78
        quiz_add_quiz_question($saq->id, $quiz);
79
        quiz_add_quiz_question($numq->id, $quiz);
80
 
81
        // Make a user to do the quiz.
82
        $user1 = $this->getDataGenerator()->create_user();
83
        $this->setUser($user1);
84
 
85
        return quiz_settings::create($quiz->id, $user1->id);
86
    }
87
 
88
    /**
89
     * Setup a quiz attempt at the quiz created by {@link prepare_quiz()}.
90
     *
91
     * @param \mod_quiz\quiz_settings $quizobj the generated quiz.
92
     * @param bool $ispreview Make the attempt a preview attempt when true.
93
     * @return array with three elements, array($quizobj, $quba, $attempt)
94
     */
95
    protected function prepare_quiz_attempt($quizobj, $ispreview = false) {
96
        // Start the attempt.
97
        $quba = \question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
98
        $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
99
 
100
        $timenow = time();
101
        $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, $ispreview);
102
        quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
103
        quiz_attempt_save_started($quizobj, $quba, $attempt);
104
 
105
        return [$quizobj, $quba, $attempt];
106
    }
107
 
108
    /**
109
     * Setup some convenience test data with a single attempt.
110
     *
111
     * @param bool $ispreview Make the attempt a preview attempt when true.
112
     * @return array with three elements, array($quizobj, $quba, $attempt)
113
     */
114
    protected function prepare_quiz_data($ispreview = false) {
115
        $quizobj = $this->prepare_quiz();
116
        return $this->prepare_quiz_attempt($quizobj, $ispreview);
117
    }
118
 
11 efrain 119
    public function test_attempt_submitted(): void {
1 efrain 120
 
1441 ariadna 121
        [$quizobj, , $attempt] = $this->prepare_quiz_data();
1 efrain 122
        $attemptobj = quiz_attempt::create($attempt->id);
123
 
124
        // Catch the event.
125
        $sink = $this->redirectEvents();
126
 
127
        $timefinish = time();
1441 ariadna 128
        $attemptobj->process_submit($timefinish, false);
1 efrain 129
        $events = $sink->get_events();
130
        $sink->close();
131
 
132
        // Validate the event.
1441 ariadna 133
        $this->assertCount(1, $events);
134
        $event = $events[0];
135
        $this->assertInstanceOf('\mod_quiz\event\attempt_submitted', $event);
136
        $this->assertEquals('quiz_attempts', $event->objecttable);
137
        $this->assertEquals($quizobj->get_context(), $event->get_context());
138
        $this->assertEquals($attempt->userid, $event->relateduserid);
139
        $this->assertEquals(null, $event->other['submitterid']); // Should be the user, but PHP Unit complains...
140
        $this->assertEventContextNotUsed($event);
141
    }
142
 
143
    /**
144
     * The \mod_quiz\event\attempt_graded event should be fired when an attempt is graded.
145
     *
146
     * @return void
147
     * @covers \mod_quiz\quiz_attempt::process_grade_submission
148
     */
149
    public function test_attempt_graded(): void {
150
 
151
        [$quizobj, , $attempt] = $this->prepare_quiz_data();
152
        $attemptobj = quiz_attempt::create($attempt->id);
153
        $timefinish = time();
154
        $attemptobj->process_submit($timefinish, false);
155
 
156
        // Catch the event.
157
        $sink = $this->redirectEvents();
158
        $attemptobj->process_grade_submission($timefinish);
159
        $events = $sink->get_events();
160
        $sink->close();
161
 
162
        // Validate the event.
1 efrain 163
        $this->assertCount(3, $events);
164
        $event = $events[2];
1441 ariadna 165
        $this->assertInstanceOf('\mod_quiz\event\attempt_graded', $event);
1 efrain 166
        $this->assertEquals('quiz_attempts', $event->objecttable);
167
        $this->assertEquals($quizobj->get_context(), $event->get_context());
168
        $this->assertEquals($attempt->userid, $event->relateduserid);
169
        $this->assertEquals(null, $event->other['submitterid']); // Should be the user, but PHP Unit complains...
170
        $this->assertEventContextNotUsed($event);
171
    }
172
 
11 efrain 173
    public function test_attempt_becameoverdue(): void {
1 efrain 174
 
175
        list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
176
        $attemptobj = quiz_attempt::create($attempt->id);
177
 
178
        // Catch the event.
179
        $sink = $this->redirectEvents();
180
        $timefinish = time();
181
        $attemptobj->process_going_overdue($timefinish, false);
182
        $events = $sink->get_events();
183
        $sink->close();
184
 
185
        $this->assertCount(1, $events);
186
        $event = $events[0];
187
        $this->assertInstanceOf('\mod_quiz\event\attempt_becameoverdue', $event);
188
        $this->assertEquals('quiz_attempts', $event->objecttable);
189
        $this->assertEquals($quizobj->get_context(), $event->get_context());
190
        $this->assertEquals($attempt->userid, $event->relateduserid);
191
        $this->assertNotEmpty($event->get_description());
192
        // Submitterid should be the user, but as we are in PHP Unit, CLI_SCRIPT is set to true which sets null in submitterid.
193
        $this->assertEquals(null, $event->other['submitterid']);
194
        $this->assertEventContextNotUsed($event);
195
    }
196
 
11 efrain 197
    public function test_attempt_abandoned(): void {
1 efrain 198
 
199
        list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
200
        $attemptobj = quiz_attempt::create($attempt->id);
201
 
202
        // Catch the event.
203
        $sink = $this->redirectEvents();
204
        $timefinish = time();
205
        $attemptobj->process_abandon($timefinish, false);
206
        $events = $sink->get_events();
207
        $sink->close();
208
 
209
        $this->assertCount(1, $events);
210
        $event = $events[0];
211
        $this->assertInstanceOf('\mod_quiz\event\attempt_abandoned', $event);
212
        $this->assertEquals('quiz_attempts', $event->objecttable);
213
        $this->assertEquals($quizobj->get_context(), $event->get_context());
214
        $this->assertEquals($attempt->userid, $event->relateduserid);
215
        // Submitterid should be the user, but as we are in PHP Unit, CLI_SCRIPT is set to true which sets null in submitterid.
216
        $this->assertEquals(null, $event->other['submitterid']);
217
        $this->assertEventContextNotUsed($event);
218
    }
219
 
11 efrain 220
    public function test_attempt_started(): void {
1 efrain 221
        $quizobj = $this->prepare_quiz();
222
 
223
        $quba = \question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
224
        $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
225
 
226
        $timenow = time();
227
        $attempt = quiz_create_attempt($quizobj, 1, false, $timenow);
228
        quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
229
 
230
        // Trigger and capture the event.
231
        $sink = $this->redirectEvents();
232
        quiz_attempt_save_started($quizobj, $quba, $attempt);
233
        $events = $sink->get_events();
234
        $event = reset($events);
235
 
236
        // Check that the event data is valid.
237
        $this->assertInstanceOf('\mod_quiz\event\attempt_started', $event);
238
        $this->assertEquals('quiz_attempts', $event->objecttable);
239
        $this->assertEquals($attempt->id, $event->objectid);
240
        $this->assertEquals($attempt->userid, $event->relateduserid);
241
        $this->assertEquals($quizobj->get_context(), $event->get_context());
242
        $this->assertEquals(\context_module::instance($quizobj->get_cmid()), $event->get_context());
243
    }
244
 
245
    /**
246
     * Test the attempt question restarted event.
247
     *
248
     * There is no external API for replacing a question, so the unit test will simply
249
     * create and trigger the event and ensure the event data is returned as expected.
250
     */
11 efrain 251
    public function test_attempt_question_restarted(): void {
1 efrain 252
        list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
253
 
254
        $params = [
255
            'objectid' => 1,
256
            'relateduserid' => 2,
257
            'courseid' => $quizobj->get_courseid(),
258
            'context' => \context_module::instance($quizobj->get_cmid()),
259
            'other' => [
260
                'quizid' => $quizobj->get_quizid(),
261
                'page' => 2,
262
                'slot' => 3,
263
                'newquestionid' => 2
264
            ]
265
        ];
266
        $event = \mod_quiz\event\attempt_question_restarted::create($params);
267
 
268
        // Trigger and capture the event.
269
        $sink = $this->redirectEvents();
270
        $event->trigger();
271
        $events = $sink->get_events();
272
        $event = reset($events);
273
 
274
        // Check that the event data is valid.
275
        $this->assertInstanceOf('\mod_quiz\event\attempt_question_restarted', $event);
276
        $this->assertEquals(\context_module::instance($quizobj->get_cmid()), $event->get_context());
277
        $this->assertEventContextNotUsed($event);
278
    }
279
 
280
    /**
281
     * Test the attempt updated event.
282
     *
283
     * There is no external API for updating an attempt, so the unit test will simply
284
     * create and trigger the event and ensure the event data is returned as expected.
285
     */
11 efrain 286
    public function test_attempt_updated(): void {
1 efrain 287
        list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
288
 
289
        $params = [
290
            'objectid' => 1,
291
            'relateduserid' => 2,
292
            'courseid' => $quizobj->get_courseid(),
293
            'context' => \context_module::instance($quizobj->get_cmid()),
294
            'other' => [
295
                'quizid' => $quizobj->get_quizid(),
296
                'page' => 0
297
            ]
298
        ];
299
        $event = \mod_quiz\event\attempt_updated::create($params);
300
 
301
        // Trigger and capture the event.
302
        $sink = $this->redirectEvents();
303
        $event->trigger();
304
        $events = $sink->get_events();
305
        $event = reset($events);
306
 
307
        // Check that the event data is valid.
308
        $this->assertInstanceOf('\mod_quiz\event\attempt_updated', $event);
309
        $this->assertEquals(\context_module::instance($quizobj->get_cmid()), $event->get_context());
310
        $this->assertEventContextNotUsed($event);
311
    }
312
 
313
    /**
314
     * Test the attempt auto-saved event.
315
     *
316
     * There is no external API for auto-saving an attempt, so the unit test will simply
317
     * create and trigger the event and ensure the event data is returned as expected.
318
     */
11 efrain 319
    public function test_attempt_autosaved(): void {
1 efrain 320
        list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
321
 
322
        $params = [
323
            'objectid' => 1,
324
            'relateduserid' => 2,
325
            'courseid' => $quizobj->get_courseid(),
326
            'context' => \context_module::instance($quizobj->get_cmid()),
327
            'other' => [
328
                'quizid' => $quizobj->get_quizid(),
329
                'page' => 0
330
            ]
331
        ];
332
 
333
        $event = \mod_quiz\event\attempt_autosaved::create($params);
334
 
335
        // Trigger and capture the event.
336
        $sink = $this->redirectEvents();
337
        $event->trigger();
338
        $events = $sink->get_events();
339
        $event = reset($events);
340
 
341
        // Check that the event data is valid.
342
        $this->assertInstanceOf('\mod_quiz\event\attempt_autosaved', $event);
343
        $this->assertEquals(\context_module::instance($quizobj->get_cmid()), $event->get_context());
344
        $this->assertEventContextNotUsed($event);
345
    }
346
 
347
    /**
348
     * Test the edit page viewed event.
349
     *
350
     * There is no external API for updating a quiz, so the unit test will simply
351
     * create and trigger the event and ensure the event data is returned as expected.
352
     */
11 efrain 353
    public function test_edit_page_viewed(): void {
1 efrain 354
        $this->resetAfterTest();
355
 
356
        $this->setAdminUser();
357
        $course = $this->getDataGenerator()->create_course();
358
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
359
 
360
        $params = [
361
            'courseid' => $course->id,
362
            'context' => \context_module::instance($quiz->cmid),
363
            'other' => [
364
                'quizid' => $quiz->id
365
            ]
366
        ];
367
        $event = \mod_quiz\event\edit_page_viewed::create($params);
368
 
369
        // Trigger and capture the event.
370
        $sink = $this->redirectEvents();
371
        $event->trigger();
372
        $events = $sink->get_events();
373
        $event = reset($events);
374
 
375
        // Check that the event data is valid.
376
        $this->assertInstanceOf('\mod_quiz\event\edit_page_viewed', $event);
377
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
378
        $this->assertEventContextNotUsed($event);
379
    }
380
 
381
    /**
382
     * Test the attempt deleted event.
383
     */
11 efrain 384
    public function test_attempt_deleted(): void {
1 efrain 385
        list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
386
 
387
        // Trigger and capture the event.
388
        $sink = $this->redirectEvents();
389
        quiz_delete_attempt($attempt, $quizobj->get_quiz());
390
        $events = $sink->get_events();
391
        $event = reset($events);
392
 
393
        // Check that the event data is valid.
394
        $this->assertInstanceOf('\mod_quiz\event\attempt_deleted', $event);
395
        $this->assertEquals(\context_module::instance($quizobj->get_cmid()), $event->get_context());
396
        $this->assertEventContextNotUsed($event);
397
    }
398
 
399
    /**
400
     * Test that preview attempt deletions are not logged.
401
     */
11 efrain 402
    public function test_preview_attempt_deleted(): void {
1 efrain 403
        // Create quiz with preview attempt.
404
        list($quizobj, $quba, $previewattempt) = $this->prepare_quiz_data(true);
405
 
406
        // Delete a preview attempt, capturing events.
407
        $sink = $this->redirectEvents();
408
        quiz_delete_attempt($previewattempt, $quizobj->get_quiz());
409
 
410
        // Verify that no events were generated.
411
        $this->assertEmpty($sink->get_events());
412
    }
413
 
414
    /**
415
     * Test the report viewed event.
416
     *
417
     * There is no external API for viewing reports, so the unit test will simply
418
     * create and trigger the event and ensure the event data is returned as expected.
419
     */
11 efrain 420
    public function test_report_viewed(): void {
1 efrain 421
        $this->resetAfterTest();
422
 
423
        $this->setAdminUser();
424
        $course = $this->getDataGenerator()->create_course();
425
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
426
 
427
        $params = [
428
            'context' => $context = \context_module::instance($quiz->cmid),
429
            'other' => [
430
                'quizid' => $quiz->id,
431
                'reportname' => 'overview'
432
            ]
433
        ];
434
        $event = \mod_quiz\event\report_viewed::create($params);
435
 
436
        // Trigger and capture the event.
437
        $sink = $this->redirectEvents();
438
        $event->trigger();
439
        $events = $sink->get_events();
440
        $event = reset($events);
441
 
442
        // Check that the event data is valid.
443
        $this->assertInstanceOf('\mod_quiz\event\report_viewed', $event);
444
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
445
        $this->assertEventContextNotUsed($event);
446
    }
447
 
448
    /**
449
     * Test the attempt reviewed event.
450
     *
451
     * There is no external API for reviewing attempts, so the unit test will simply
452
     * create and trigger the event and ensure the event data is returned as expected.
453
     */
11 efrain 454
    public function test_attempt_reviewed(): void {
1 efrain 455
        $this->resetAfterTest();
456
 
457
        $this->setAdminUser();
458
        $course = $this->getDataGenerator()->create_course();
459
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
460
 
461
        $params = [
462
            'objectid' => 1,
463
            'relateduserid' => 2,
464
            'courseid' => $course->id,
465
            'context' => \context_module::instance($quiz->cmid),
466
            'other' => [
467
                'quizid' => $quiz->id
468
            ]
469
        ];
470
        $event = \mod_quiz\event\attempt_reviewed::create($params);
471
 
472
        // Trigger and capture the event.
473
        $sink = $this->redirectEvents();
474
        $event->trigger();
475
        $events = $sink->get_events();
476
        $event = reset($events);
477
 
478
        // Check that the event data is valid.
479
        $this->assertInstanceOf('\mod_quiz\event\attempt_reviewed', $event);
480
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
481
        $this->assertEventContextNotUsed($event);
482
    }
483
 
484
    /**
485
     * Test the attempt summary viewed event.
486
     *
487
     * There is no external API for viewing the attempt summary, so the unit test will simply
488
     * create and trigger the event and ensure the event data is returned as expected.
489
     */
11 efrain 490
    public function test_attempt_summary_viewed(): void {
1 efrain 491
        $this->resetAfterTest();
492
 
493
        $this->setAdminUser();
494
        $course = $this->getDataGenerator()->create_course();
495
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
496
 
497
        $params = [
498
            'objectid' => 1,
499
            'relateduserid' => 2,
500
            'courseid' => $course->id,
501
            'context' => \context_module::instance($quiz->cmid),
502
            'other' => [
503
                'quizid' => $quiz->id
504
            ]
505
        ];
506
        $event = \mod_quiz\event\attempt_summary_viewed::create($params);
507
 
508
        // Trigger and capture the event.
509
        $sink = $this->redirectEvents();
510
        $event->trigger();
511
        $events = $sink->get_events();
512
        $event = reset($events);
513
 
514
        // Check that the event data is valid.
515
        $this->assertInstanceOf('\mod_quiz\event\attempt_summary_viewed', $event);
516
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
517
        $this->assertEventContextNotUsed($event);
518
    }
519
 
520
    /**
521
     * Test the user override created event.
522
     *
523
     * There is no external API for creating a user override, so the unit test will simply
524
     * create and trigger the event and ensure the event data is returned as expected.
525
     */
11 efrain 526
    public function test_user_override_created(): void {
1 efrain 527
        $this->resetAfterTest();
528
 
529
        $this->setAdminUser();
530
        $course = $this->getDataGenerator()->create_course();
531
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
532
 
533
        $params = [
534
            'objectid' => 1,
535
            'relateduserid' => 2,
536
            'context' => \context_module::instance($quiz->cmid),
537
            'other' => [
538
                'quizid' => $quiz->id
539
            ]
540
        ];
541
        $event = \mod_quiz\event\user_override_created::create($params);
542
 
543
        // Trigger and capture the event.
544
        $sink = $this->redirectEvents();
545
        $event->trigger();
546
        $events = $sink->get_events();
547
        $event = reset($events);
548
 
549
        // Check that the event data is valid.
550
        $this->assertInstanceOf('\mod_quiz\event\user_override_created', $event);
551
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
552
        $this->assertEventContextNotUsed($event);
553
    }
554
 
555
    /**
556
     * Test the group override created event.
557
     *
558
     * There is no external API for creating a group override, so the unit test will simply
559
     * create and trigger the event and ensure the event data is returned as expected.
560
     */
11 efrain 561
    public function test_group_override_created(): void {
1 efrain 562
        $this->resetAfterTest();
563
 
564
        $this->setAdminUser();
565
        $course = $this->getDataGenerator()->create_course();
566
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
567
 
568
        $params = [
569
            'objectid' => 1,
570
            'context' => \context_module::instance($quiz->cmid),
571
            'other' => [
572
                'quizid' => $quiz->id,
573
                'groupid' => 2
574
            ]
575
        ];
576
        $event = \mod_quiz\event\group_override_created::create($params);
577
 
578
        // Trigger and capture the event.
579
        $sink = $this->redirectEvents();
580
        $event->trigger();
581
        $events = $sink->get_events();
582
        $event = reset($events);
583
 
584
        // Check that the event data is valid.
585
        $this->assertInstanceOf('\mod_quiz\event\group_override_created', $event);
586
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
587
        $this->assertEventContextNotUsed($event);
588
    }
589
 
590
    /**
591
     * Test the user override updated event.
592
     *
593
     * There is no external API for updating a user override, so the unit test will simply
594
     * create and trigger the event and ensure the event data is returned as expected.
595
     */
11 efrain 596
    public function test_user_override_updated(): void {
1 efrain 597
        $this->resetAfterTest();
598
 
599
        $this->setAdminUser();
600
        $course = $this->getDataGenerator()->create_course();
601
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
602
 
603
        $params = [
604
            'objectid' => 1,
605
            'relateduserid' => 2,
606
            'context' => \context_module::instance($quiz->cmid),
607
            'other' => [
608
                'quizid' => $quiz->id
609
            ]
610
        ];
611
        $event = \mod_quiz\event\user_override_updated::create($params);
612
 
613
        // Trigger and capture the event.
614
        $sink = $this->redirectEvents();
615
        $event->trigger();
616
        $events = $sink->get_events();
617
        $event = reset($events);
618
 
619
        // Check that the event data is valid.
620
        $this->assertInstanceOf('\mod_quiz\event\user_override_updated', $event);
621
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
622
        $this->assertEventContextNotUsed($event);
623
    }
624
 
625
    /**
626
     * Test the group override updated event.
627
     *
628
     * There is no external API for updating a group override, so the unit test will simply
629
     * create and trigger the event and ensure the event data is returned as expected.
630
     */
11 efrain 631
    public function test_group_override_updated(): void {
1 efrain 632
        $this->resetAfterTest();
633
 
634
        $this->setAdminUser();
635
        $course = $this->getDataGenerator()->create_course();
636
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
637
 
638
        $params = [
639
            'objectid' => 1,
640
            'context' => \context_module::instance($quiz->cmid),
641
            'other' => [
642
                'quizid' => $quiz->id,
643
                'groupid' => 2
644
            ]
645
        ];
646
        $event = \mod_quiz\event\group_override_updated::create($params);
647
 
648
        // Trigger and capture the event.
649
        $sink = $this->redirectEvents();
650
        $event->trigger();
651
        $events = $sink->get_events();
652
        $event = reset($events);
653
 
654
        // Check that the event data is valid.
655
        $this->assertInstanceOf('\mod_quiz\event\group_override_updated', $event);
656
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
657
        $this->assertEventContextNotUsed($event);
658
    }
659
 
660
    /**
661
     * Test the user override deleted event.
662
     */
11 efrain 663
    public function test_user_override_deleted(): void {
1 efrain 664
        global $DB;
665
 
666
        $this->resetAfterTest();
667
 
668
        $this->setAdminUser();
669
        $course = $this->getDataGenerator()->create_course();
670
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
671
        $quizsettings = quiz_settings::create($quiz->id);
672
 
673
        // Create an override.
674
        $override = new \stdClass();
675
        $override->quiz = $quiz->id;
676
        $override->userid = 2;
677
        $override->id = $DB->insert_record('quiz_overrides', $override);
678
 
679
        // Trigger and capture the event.
680
        $sink = $this->redirectEvents();
681
        $quizsettings->get_override_manager()->delete_overrides(overrides: [$override]);
682
        $events = $sink->get_events();
683
        $event = reset($events);
684
 
685
        // Check that the event data is valid.
686
        $this->assertInstanceOf('\mod_quiz\event\user_override_deleted', $event);
687
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
688
        $this->assertEventContextNotUsed($event);
689
    }
690
 
691
    /**
692
     * Test the group override deleted event.
693
     */
11 efrain 694
    public function test_group_override_deleted(): void {
1 efrain 695
        global $DB;
696
 
697
        $this->resetAfterTest();
698
 
699
        $this->setAdminUser();
700
        $course = $this->getDataGenerator()->create_course();
701
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
702
        $quizsettings = quiz_settings::create($quiz->id);
703
 
704
        // Create an override.
705
        $override = new \stdClass();
706
        $override->quiz = $quiz->id;
707
        $override->groupid = 2;
708
        $override->id = $DB->insert_record('quiz_overrides', $override);
709
 
710
        // Trigger and capture the event.
711
        $sink = $this->redirectEvents();
712
        $quizsettings->get_override_manager()->delete_overrides(overrides: [$override]);
713
        $events = $sink->get_events();
714
        $event = reset($events);
715
 
716
        // Check that the event data is valid.
717
        $this->assertInstanceOf('\mod_quiz\event\group_override_deleted', $event);
718
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
719
        $this->assertEventContextNotUsed($event);
720
    }
721
 
722
    /**
723
     * Test the attempt viewed event.
724
     *
725
     * There is no external API for continuing an attempt, so the unit test will simply
726
     * create and trigger the event and ensure the event data is returned as expected.
727
     */
11 efrain 728
    public function test_attempt_viewed(): void {
1 efrain 729
        $this->resetAfterTest();
730
 
731
        $this->setAdminUser();
732
        $course = $this->getDataGenerator()->create_course();
733
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
734
 
735
        $params = [
736
            'objectid' => 1,
737
            'relateduserid' => 2,
738
            'courseid' => $course->id,
739
            'context' => \context_module::instance($quiz->cmid),
740
            'other' => [
741
                'quizid' => $quiz->id,
742
                'page' => 0
743
            ]
744
        ];
745
        $event = \mod_quiz\event\attempt_viewed::create($params);
746
 
747
        // Trigger and capture the event.
748
        $sink = $this->redirectEvents();
749
        $event->trigger();
750
        $events = $sink->get_events();
751
        $event = reset($events);
752
 
753
        // Check that the event data is valid.
754
        $this->assertInstanceOf('\mod_quiz\event\attempt_viewed', $event);
755
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
756
        $this->assertEventContextNotUsed($event);
757
    }
758
 
759
    /**
760
     * Test the attempt previewed event.
761
     */
11 efrain 762
    public function test_attempt_preview_started(): void {
1 efrain 763
        $quizobj = $this->prepare_quiz();
764
 
765
        $quba = \question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
766
        $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
767
 
768
        $timenow = time();
769
        $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, true);
770
        quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
771
 
772
        // Trigger and capture the event.
773
        $sink = $this->redirectEvents();
774
        quiz_attempt_save_started($quizobj, $quba, $attempt);
775
        $events = $sink->get_events();
776
        $event = reset($events);
777
 
778
        // Check that the event data is valid.
779
        $this->assertInstanceOf('\mod_quiz\event\attempt_preview_started', $event);
780
        $this->assertEquals(\context_module::instance($quizobj->get_cmid()), $event->get_context());
781
        $this->assertEventContextNotUsed($event);
782
    }
783
 
784
    /**
785
     * Test the question manually graded event.
786
     *
787
     * There is no external API for manually grading a question, so the unit test will simply
788
     * create and trigger the event and ensure the event data is returned as expected.
789
     */
11 efrain 790
    public function test_question_manually_graded(): void {
1 efrain 791
        list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
792
 
793
        $params = [
794
            'objectid' => 1,
795
            'courseid' => $quizobj->get_courseid(),
796
            'context' => \context_module::instance($quizobj->get_cmid()),
797
            'other' => [
798
                'quizid' => $quizobj->get_quizid(),
799
                'attemptid' => 2,
800
                'slot' => 3
801
            ]
802
        ];
803
        $event = \mod_quiz\event\question_manually_graded::create($params);
804
 
805
        // Trigger and capture the event.
806
        $sink = $this->redirectEvents();
807
        $event->trigger();
808
        $events = $sink->get_events();
809
        $event = reset($events);
810
 
811
        // Check that the event data is valid.
812
        $this->assertInstanceOf('\mod_quiz\event\question_manually_graded', $event);
813
        $this->assertEquals(\context_module::instance($quizobj->get_cmid()), $event->get_context());
814
        $this->assertEventContextNotUsed($event);
815
    }
816
 
817
    /**
818
     * Test the attempt regraded event.
819
     *
820
     * There is no external API for regrading attempts, so the unit test will simply
821
     * create and trigger the event and ensure the event data is returned as expected.
822
     */
11 efrain 823
    public function test_attempt_regraded(): void {
1 efrain 824
        $this->resetAfterTest();
825
 
826
        $this->setAdminUser();
827
        $course = $this->getDataGenerator()->create_course();
828
        $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
829
 
830
        $params = [
831
            'objectid' => 1,
832
            'relateduserid' => 2,
833
            'courseid' => $course->id,
834
            'context' => \context_module::instance($quiz->cmid),
835
            'other' => [
836
                'quizid' => $quiz->id
837
            ]
838
        ];
839
        $event = \mod_quiz\event\attempt_regraded::create($params);
840
 
841
        // Trigger and capture the event.
842
        $sink = $this->redirectEvents();
843
        $event->trigger();
844
        $events = $sink->get_events();
845
        $event = reset($events);
846
 
847
        // Check that the event data is valid.
848
        $this->assertInstanceOf('\mod_quiz\event\attempt_regraded', $event);
849
        $this->assertEquals(\context_module::instance($quiz->cmid), $event->get_context());
850
        $this->assertEventContextNotUsed($event);
851
    }
852
 
853
    /**
854
     * Test the attempt notify manual graded event.
855
     * There is no external API for notification email when manual grading of user's attempt is completed,
856
     * so the unit test will simply create and trigger the event and ensure the event data is returned as expected.
857
     */
11 efrain 858
    public function test_attempt_manual_grading_completed(): void {
1 efrain 859
        $this->resetAfterTest();
860
        list($quizobj, $quba, $attempt) = $this->prepare_quiz_data();
861
        $attemptobj = quiz_attempt::create($attempt->id);
862
 
863
        $params = [
864
            'objectid' => $attemptobj->get_attemptid(),
865
            'relateduserid' => $attemptobj->get_userid(),
866
            'courseid' => $attemptobj->get_course()->id,
867
            'context' => \context_module::instance($attemptobj->get_cmid()),
868
            'other' => [
869
                'quizid' => $attemptobj->get_quizid()
870
            ]
871
        ];
872
        $event = \mod_quiz\event\attempt_manual_grading_completed::create($params);
873
 
874
        // Catch the event.
875
        $sink = $this->redirectEvents();
876
        $event->trigger();
877
        $events = $sink->get_events();
878
        $sink->close();
879
 
880
        // Validate the event.
881
        $this->assertCount(1, $events);
882
        $event = reset($events);
883
        $this->assertInstanceOf('\mod_quiz\event\attempt_manual_grading_completed', $event);
884
        $this->assertEquals('quiz_attempts', $event->objecttable);
885
        $this->assertEquals($quizobj->get_context(), $event->get_context());
886
        $this->assertEquals($attempt->userid, $event->relateduserid);
887
        $this->assertNotEmpty($event->get_description());
888
        $this->assertEventContextNotUsed($event);
889
    }
890
 
891
    /**
892
     * Test the page break created event.
893
     *
894
     * There is no external API for creating page break, so the unit test will simply
895
     * create and trigger the event and ensure the event data is returned as expected.
896
     */
11 efrain 897
    public function test_page_break_created(): void {
1 efrain 898
        $quizobj = $this->prepare_quiz();
899
 
900
        $params = [
901
            'objectid' => 1,
902
            'context' => context_module::instance($quizobj->get_cmid()),
903
            'other' => [
904
                'quizid' => $quizobj->get_quizid(),
905
                'slotnumber' => 3,
906
            ]
907
        ];
908
        $event = \mod_quiz\event\page_break_created::create($params);
909
 
910
        // Trigger and capture the event.
911
        $sink = $this->redirectEvents();
912
        $event->trigger();
913
        $events = $sink->get_events();
914
        $event = reset($events);
915
 
916
        // Check that the event data is valid.
917
        $this->assertInstanceOf('\mod_quiz\event\page_break_created', $event);
918
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
919
        $this->assertEventContextNotUsed($event);
920
    }
921
 
922
    /**
923
     * Test the page break deleted event.
924
     *
925
     * There is no external API for deleting page break, so the unit test will simply
926
     * create and trigger the event and ensure the event data is returned as expected.
927
     */
11 efrain 928
    public function test_page_deleted_created(): void {
1 efrain 929
        $quizobj = $this->prepare_quiz();
930
 
931
        $params = [
932
            'objectid' => 1,
933
            'context' => context_module::instance($quizobj->get_cmid()),
934
            'other' => [
935
                'quizid' => $quizobj->get_quizid(),
936
                'slotnumber' => 3,
937
            ]
938
        ];
939
        $event = \mod_quiz\event\page_break_deleted::create($params);
940
 
941
        // Trigger and capture the event.
942
        $sink = $this->redirectEvents();
943
        $event->trigger();
944
        $events = $sink->get_events();
945
        $event = reset($events);
946
 
947
        // Check that the event data is valid.
948
        $this->assertInstanceOf('\mod_quiz\event\page_break_deleted', $event);
949
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
950
        $this->assertEventContextNotUsed($event);
951
    }
952
 
953
    /**
954
     * Test the quiz grade updated event.
955
     *
956
     * There is no external API for updating quiz grade, so the unit test will simply
957
     * create and trigger the event and ensure the event data is returned as expected.
958
     */
11 efrain 959
    public function test_quiz_grade_updated(): void {
1 efrain 960
        $quizobj = $this->prepare_quiz();
961
 
962
        $params = [
963
            'objectid' => $quizobj->get_quizid(),
964
            'context' => context_module::instance($quizobj->get_cmid()),
965
            'other' => [
966
                'oldgrade' => 1,
967
                'newgrade' => 3,
968
            ]
969
        ];
970
        $event = \mod_quiz\event\quiz_grade_updated::create($params);
971
 
972
        // Trigger and capture the event.
973
        $sink = $this->redirectEvents();
974
        $event->trigger();
975
        $events = $sink->get_events();
976
        $event = reset($events);
977
 
978
        // Check that the event data is valid.
979
        $this->assertInstanceOf('\mod_quiz\event\quiz_grade_updated', $event);
980
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
981
        $this->assertEventContextNotUsed($event);
982
    }
983
 
984
    /**
985
     * Test the quiz re-paginated event.
986
     *
987
     * There is no external API for re-paginating quiz, so the unit test will simply
988
     * create and trigger the event and ensure the event data is returned as expected.
989
     */
11 efrain 990
    public function test_quiz_repaginated(): void {
1 efrain 991
        $quizobj = $this->prepare_quiz();
992
 
993
        $params = [
994
            'objectid' => $quizobj->get_quizid(),
995
            'context' => context_module::instance($quizobj->get_cmid()),
996
            'other' => [
997
                'slotsperpage' => 3,
998
            ]
999
        ];
1000
        $event = \mod_quiz\event\quiz_repaginated::create($params);
1001
 
1002
        // Trigger and capture the event.
1003
        $sink = $this->redirectEvents();
1004
        $event->trigger();
1005
        $events = $sink->get_events();
1006
        $event = reset($events);
1007
 
1008
        // Check that the event data is valid.
1009
        $this->assertInstanceOf('\mod_quiz\event\quiz_repaginated', $event);
1010
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1011
        $this->assertEventContextNotUsed($event);
1012
    }
1013
 
1014
    /**
1015
     * Test the section break created event.
1016
     *
1017
     * There is no external API for creating section break, so the unit test will simply
1018
     * create and trigger the event and ensure the event data is returned as expected.
1019
     */
11 efrain 1020
    public function test_section_break_created(): void {
1 efrain 1021
        $quizobj = $this->prepare_quiz();
1022
 
1023
        $params = [
1024
            'objectid' => 1,
1025
            'context' => context_module::instance($quizobj->get_cmid()),
1026
            'other' => [
1027
                'quizid' => $quizobj->get_quizid(),
1028
                'firstslotid' => 1,
1029
                'firstslotnumber' => 2,
1030
                'title' => 'New title'
1031
            ]
1032
        ];
1033
        $event = \mod_quiz\event\section_break_created::create($params);
1034
 
1035
        // Trigger and capture the event.
1036
        $sink = $this->redirectEvents();
1037
        $event->trigger();
1038
        $events = $sink->get_events();
1039
        $event = reset($events);
1040
 
1041
        // Check that the event data is valid.
1042
        $this->assertInstanceOf('\mod_quiz\event\section_break_created', $event);
1043
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1044
        $this->assertStringContainsString($params['other']['title'], $event->get_description());
1045
        $this->assertEventContextNotUsed($event);
1046
    }
1047
 
1048
    /**
1049
     * Test the section break deleted event.
1050
     *
1051
     * There is no external API for deleting section break, so the unit test will simply
1052
     * create and trigger the event and ensure the event data is returned as expected.
1053
     */
11 efrain 1054
    public function test_section_break_deleted(): void {
1 efrain 1055
        $quizobj = $this->prepare_quiz();
1056
 
1057
        $params = [
1058
            'objectid' => 1,
1059
            'context' => context_module::instance($quizobj->get_cmid()),
1060
            'other' => [
1061
                'quizid' => $quizobj->get_quizid(),
1062
                'firstslotid' => 1,
1063
                'firstslotnumber' => 2
1064
            ]
1065
        ];
1066
        $event = \mod_quiz\event\section_break_deleted::create($params);
1067
 
1068
        // Trigger and capture the event.
1069
        $sink = $this->redirectEvents();
1070
        $event->trigger();
1071
        $events = $sink->get_events();
1072
        $event = reset($events);
1073
 
1074
        // Check that the event data is valid.
1075
        $this->assertInstanceOf('\mod_quiz\event\section_break_deleted', $event);
1076
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1077
        $this->assertEventContextNotUsed($event);
1078
    }
1079
 
1080
    /**
1081
     * Test the section shuffle updated event.
1082
     *
1083
     * There is no external API for updating section shuffle, so the unit test will simply
1084
     * create and trigger the event and ensure the event data is returned as expected.
1085
     */
11 efrain 1086
    public function test_section_shuffle_updated(): void {
1 efrain 1087
        $quizobj = $this->prepare_quiz();
1088
 
1089
        $params = [
1090
            'objectid' => 1,
1091
            'context' => context_module::instance($quizobj->get_cmid()),
1092
            'other' => [
1093
                'quizid' => $quizobj->get_quizid(),
1094
                'firstslotnumber' => 2,
1095
                'shuffle' => true
1096
            ]
1097
        ];
1098
        $event = \mod_quiz\event\section_shuffle_updated::create($params);
1099
 
1100
        // Trigger and capture the event.
1101
        $sink = $this->redirectEvents();
1102
        $event->trigger();
1103
        $events = $sink->get_events();
1104
        $event = reset($events);
1105
 
1106
        // Check that the event data is valid.
1107
        $this->assertInstanceOf('\mod_quiz\event\section_shuffle_updated', $event);
1108
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1109
        $this->assertEventContextNotUsed($event);
1110
    }
1111
 
1112
    /**
1113
     * Test the section title updated event.
1114
     *
1115
     * There is no external API for updating section title, so the unit test will simply
1116
     * create and trigger the event and ensure the event data is returned as expected.
1117
     */
11 efrain 1118
    public function test_section_title_updated(): void {
1 efrain 1119
        $quizobj = $this->prepare_quiz();
1120
 
1121
        $params = [
1122
            'objectid' => 1,
1123
            'context' => context_module::instance($quizobj->get_cmid()),
1124
            'other' => [
1125
                'quizid' => $quizobj->get_quizid(),
1126
                'firstslotid' => 1,
1127
                'firstslotnumber' => 2,
1128
                'newtitle' => 'New title'
1129
            ]
1130
        ];
1131
        $event = \mod_quiz\event\section_title_updated::create($params);
1132
 
1133
        // Trigger and capture the event.
1134
        $sink = $this->redirectEvents();
1135
        $event->trigger();
1136
        $events = $sink->get_events();
1137
        $event = reset($events);
1138
 
1139
        // Check that the event data is valid.
1140
        $this->assertInstanceOf('\mod_quiz\event\section_title_updated', $event);
1141
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1142
        $this->assertStringContainsString($params['other']['newtitle'], $event->get_description());
1143
        $this->assertEventContextNotUsed($event);
1144
    }
1145
 
1146
    /**
1147
     * Test the slot created event.
1148
     *
1149
     * There is no external API for creating slot, so the unit test will simply
1150
     * create and trigger the event and ensure the event data is returned as expected.
1151
     */
11 efrain 1152
    public function test_slot_created(): void {
1 efrain 1153
        $quizobj = $this->prepare_quiz();
1154
 
1155
        $params = [
1156
            'objectid' => 1,
1157
            'context' => context_module::instance($quizobj->get_cmid()),
1158
            'other' => [
1159
                'quizid' => $quizobj->get_quizid(),
1160
                'slotnumber' => 1,
1161
                'page' => 1
1162
            ]
1163
        ];
1164
        $event = \mod_quiz\event\slot_created::create($params);
1165
 
1166
        // Trigger and capture the event.
1167
        $sink = $this->redirectEvents();
1168
        $event->trigger();
1169
        $events = $sink->get_events();
1170
        $event = reset($events);
1171
 
1172
        // Check that the event data is valid.
1173
        $this->assertInstanceOf('\mod_quiz\event\slot_created', $event);
1174
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1175
        $this->assertEventContextNotUsed($event);
1176
    }
1177
 
1178
    /**
1179
     * Test the slot deleted event.
1180
     *
1181
     * There is no external API for deleting slot, so the unit test will simply
1182
     * create and trigger the event and ensure the event data is returned as expected.
1183
     */
11 efrain 1184
    public function test_slot_deleted(): void {
1 efrain 1185
        $quizobj = $this->prepare_quiz();
1186
 
1187
        $params = [
1188
            'objectid' => 1,
1189
            'context' => context_module::instance($quizobj->get_cmid()),
1190
            'other' => [
1191
                'quizid' => $quizobj->get_quizid(),
1192
                'slotnumber' => 1,
1193
            ]
1194
        ];
1195
        $event = \mod_quiz\event\slot_deleted::create($params);
1196
 
1197
        // Trigger and capture the event.
1198
        $sink = $this->redirectEvents();
1199
        $event->trigger();
1200
        $events = $sink->get_events();
1201
        $event = reset($events);
1202
 
1203
        // Check that the event data is valid.
1204
        $this->assertInstanceOf('\mod_quiz\event\slot_deleted', $event);
1205
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1206
        $this->assertEventContextNotUsed($event);
1207
    }
1208
 
1209
    /**
1210
     * Test the slot mark updated event.
1211
     *
1212
     * There is no external API for updating slot mark, so the unit test will simply
1213
     * create and trigger the event and ensure the event data is returned as expected.
1214
     */
11 efrain 1215
    public function test_slot_mark_updated(): void {
1 efrain 1216
        $quizobj = $this->prepare_quiz();
1217
 
1218
        $params = [
1219
            'objectid' => 1,
1220
            'context' => context_module::instance($quizobj->get_cmid()),
1221
            'other' => [
1222
                'quizid' => $quizobj->get_quizid(),
1223
                'previousmaxmark' => 1,
1224
                'newmaxmark' => 2,
1225
            ]
1226
        ];
1227
        $event = \mod_quiz\event\slot_mark_updated::create($params);
1228
 
1229
        // Trigger and capture the event.
1230
        $sink = $this->redirectEvents();
1231
        $event->trigger();
1232
        $events = $sink->get_events();
1233
        $event = reset($events);
1234
 
1235
        // Check that the event data is valid.
1236
        $this->assertInstanceOf('\mod_quiz\event\slot_mark_updated', $event);
1237
        $this->assertEquals($quizobj->get_context(), $event->get_context());
1238
        $this->assertEventContextNotUsed($event);
1239
    }
1240
 
1441 ariadna 1241
    public function test_slot_version_updated(): void {
1242
        $quizobj = $this->prepare_quiz();
1243
        $this->setAdminUser();
1244
 
1245
        $quizobj->preload_questions();
1246
        [, $numqslotid] = array_column($quizobj->get_questions(null, false), 'slotid');
1247
 
1248
        $sink = $this->redirectEvents();
1249
        submit_question_version::execute($numqslotid, 2);
1250
        $events = $sink->get_events();
1251
        $event = reset($events);
1252
 
1253
        // Check that the event data is valid.
1254
        $expecteddesc = "The user with id '2' updated the slot with id '$numqslotid' " .
1255
            "belonging to the quiz with course module id '{$quizobj->get_cmid()}'. " .
1256
            "Its question version was changed from 'Always latest' to '2'.";
1257
        $this->assertInstanceOf('\mod_quiz\event\slot_version_updated', $event);
1258
        $this->assertEquals($quizobj->get_context(), $event->get_context());
1259
        $this->assertEquals($expecteddesc, $event->get_description());
1260
        $this->assertEventContextNotUsed($event);
1261
    }
1262
 
1 efrain 1263
    /**
1264
     * Test quiz_grade_item_created.
1265
     *
1266
     * @covers \mod_quiz\event\quiz_grade_item_created
1267
     */
1268
    public function test_quiz_grade_item_created(): void {
1269
        global $USER;
1270
 
1271
        $quizobj = $this->prepare_quiz();
1272
        $stucture = $quizobj->get_structure();
1273
 
1274
        // Trigger and capture the event.
1275
        $sink = $this->redirectEvents();
1276
        $stucture->create_grade_item((object) ['quizid' => $quizobj->get_quizid(), 'name' => 'Test']);
1277
        $events = $sink->get_events();
1278
        /** @var slot_grade_item_updated $event */
1279
        $event = reset($events);
1280
 
1281
        // Check that the event data is valid.
1282
        $stucture = $quizobj->get_structure();
1283
        $gradeitem = array_values($stucture->get_grade_items())[0];
1284
        $this->assertInstanceOf(quiz_grade_item_created::class, $event);
1285
        $this->assertEquals($quizobj->get_context(), $event->get_context());
1286
        $this->assertEventContextNotUsed($event);
1287
        $this->assertEquals(new \moodle_url('/mod/quiz/editgrading.php', ['cmid' => $quizobj->get_cmid()]),
1288
            $event->get_url());
1289
        $this->assertEquals("The user with id '$USER->id' created quiz grade item with id '$gradeitem->id' " .
1290
            "for the quiz with course module id '{$quizobj->get_cmid()}'.",
1291
            $event->get_description());
1292
    }
1293
 
1294
    /**
1295
     * Test quiz_grade_item_updated.
1296
     *
1297
     * @covers \mod_quiz\event\quiz_grade_item_updated
1298
     */
1299
    public function test_quiz_grade_item_updated(): void {
1300
        global $USER;
1301
 
1302
        $quizobj = $this->prepare_quiz();
1303
        /** @var \mod_quiz_generator $quizgenerator */
1304
        $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
1305
        $gradeitem = $quizgenerator->create_grade_item(
1306
            ['quizid' => $quizobj->get_quizid(), 'name' => 'Awesomeness!']);
1307
        $stucture = $quizobj->get_structure();
1308
 
1309
        // Trigger and capture the event.
1310
        $sink = $this->redirectEvents();
1311
        $stucture->update_grade_item((object) ['id' => $gradeitem->id, 'name' => 'Test']);
1312
        $events = $sink->get_events();
1313
        /** @var slot_grade_item_updated $event */
1314
        $event = reset($events);
1315
 
1316
        // Check that the event data is valid.
1317
        $this->assertInstanceOf(quiz_grade_item_updated::class, $event);
1318
        $this->assertEquals($quizobj->get_context(), $event->get_context());
1319
        $this->assertEventContextNotUsed($event);
1320
        $this->assertEquals(new \moodle_url('/mod/quiz/editgrading.php', ['cmid' => $quizobj->get_cmid()]),
1321
            $event->get_url());
1322
        $this->assertEquals("The user with id '$USER->id' updated quiz grade item with id '$gradeitem->id' " .
1323
            "for the quiz with course module id '{$quizobj->get_cmid()}'.",
1324
            $event->get_description());
1325
    }
1326
 
1327
    /**
1328
     * Test quiz_grade_item_deleted.
1329
     *
1330
     * @covers \mod_quiz\event\quiz_grade_item_deleted
1331
     */
1332
    public function test_quiz_grade_item_deleted(): void {
1333
        global $USER;
1334
 
1335
        $quizobj = $this->prepare_quiz();
1336
        /** @var \mod_quiz_generator $quizgenerator */
1337
        $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
1338
        $gradeitem = $quizgenerator->create_grade_item(
1339
            ['quizid' => $quizobj->get_quizid(), 'name' => 'Awesomeness!']);
1340
        $stucture = $quizobj->get_structure();
1341
 
1342
        // Trigger and capture the event.
1343
        $sink = $this->redirectEvents();
1344
        $stucture->delete_grade_item($gradeitem->id);
1345
        $events = $sink->get_events();
1346
        /** @var slot_grade_item_updated $event */
1347
        $event = reset($events);
1348
 
1349
        // Check that the event data is valid.
1350
        $this->assertInstanceOf(quiz_grade_item_deleted::class, $event);
1351
        $this->assertEquals($quizobj->get_context(), $event->get_context());
1352
        $this->assertEventContextNotUsed($event);
1353
        $this->assertEquals(new \moodle_url('/mod/quiz/editgrading.php', ['cmid' => $quizobj->get_cmid()]),
1354
            $event->get_url());
1355
        $this->assertEquals("The user with id '$USER->id' deleted quiz grade item with id '$gradeitem->id' " .
1356
            "for the quiz with course module id '{$quizobj->get_cmid()}'.",
1357
            $event->get_description());
1358
    }
1359
 
1360
    /**
1361
     * Test slot_grade_item_updated.
1362
     *
1363
     * @covers \mod_quiz\event\slot_grade_item_updated
1364
     */
1365
    public function test_slot_grade_item_updated(): void {
1366
        global $USER;
1367
 
1368
        $quizobj = $this->prepare_quiz();
1369
        /** @var \mod_quiz_generator $quizgenerator */
1370
        $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
1371
        $gradeitem = $quizgenerator->create_grade_item(
1372
            ['quizid' => $quizobj->get_quizid(), 'name' => 'Awesomeness!']);
1373
        $stucture = $quizobj->get_structure();
1374
        $slot = $stucture->get_slot_by_number(1);
1375
 
1376
        // Trigger and capture the event.
1377
        $sink = $this->redirectEvents();
1378
        $stucture->update_slot_grade_item($slot, $gradeitem->id);
1379
        $events = $sink->get_events();
1380
        /** @var slot_grade_item_updated $event */
1381
        $event = reset($events);
1382
 
1383
        // Check that the event data is valid.
1384
        $this->assertInstanceOf(slot_grade_item_updated::class, $event);
1385
        $this->assertEquals($quizobj->get_context(), $event->get_context());
1386
        $this->assertEventContextNotUsed($event);
1387
        $this->assertEquals(new \moodle_url('/mod/quiz/editgrading.php', ['cmid' => $quizobj->get_cmid()]),
1388
            $event->get_url());
1389
        $this->assertEquals("The user with id '$USER->id' updated the slot with id '{$slot->id}' " .
1390
            "belonging to the quiz with course module id '{$quizobj->get_cmid()}'. " .
1391
            "The grade item this slot contributes to was changed from '' to '$gradeitem->id'.",
1392
            $event->get_description());
1393
 
1394
        // Check nothing logged if the value is not changed.
1395
        $sink = $this->redirectEvents();
1396
        $stucture->update_slot_grade_item($slot, $gradeitem->id);
1397
        $events = $sink->get_events();
1398
        $this->assertCount(0, $events);
1399
    }
1400
 
1401
    /**
1402
     * Test the slot moved event.
1403
     *
1404
     * There is no external API for moving slot, so the unit test will simply
1405
     * create and trigger the event and ensure the event data is returned as expected.
1406
     */
11 efrain 1407
    public function test_slot_moved(): void {
1 efrain 1408
        $quizobj = $this->prepare_quiz();
1409
 
1410
        $params = [
1411
            'objectid' => 1,
1412
            'context' => context_module::instance($quizobj->get_cmid()),
1413
            'other' => [
1414
                'quizid' => $quizobj->get_quizid(),
1415
                'previousslotnumber' => 1,
1416
                'afterslotnumber' => 2,
1417
                'page' => 1
1418
            ]
1419
        ];
1420
        $event = \mod_quiz\event\slot_moved::create($params);
1421
 
1422
        // Trigger and capture the event.
1423
        $sink = $this->redirectEvents();
1424
        $event->trigger();
1425
        $events = $sink->get_events();
1426
        $event = reset($events);
1427
 
1428
        // Check that the event data is valid.
1429
        $this->assertInstanceOf('\mod_quiz\event\slot_moved', $event);
1430
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1431
        $this->assertEventContextNotUsed($event);
1432
    }
1433
 
1434
    /**
1435
     * Test the slot require previous updated event.
1436
     *
1437
     * There is no external API for updating slot require previous option, so the unit test will simply
1438
     * create and trigger the event and ensure the event data is returned as expected.
1439
     */
11 efrain 1440
    public function test_slot_requireprevious_updated(): void {
1 efrain 1441
        $quizobj = $this->prepare_quiz();
1442
 
1443
        $params = [
1444
            'objectid' => 1,
1445
            'context' => context_module::instance($quizobj->get_cmid()),
1446
            'other' => [
1447
                'quizid' => $quizobj->get_quizid(),
1448
                'requireprevious' => true
1449
            ]
1450
        ];
1451
        $event = \mod_quiz\event\slot_requireprevious_updated::create($params);
1452
 
1453
        // Trigger and capture the event.
1454
        $sink = $this->redirectEvents();
1455
        $event->trigger();
1456
        $events = $sink->get_events();
1457
        $event = reset($events);
1458
 
1459
        // Check that the event data is valid.
1460
        $this->assertInstanceOf('\mod_quiz\event\slot_requireprevious_updated', $event);
1461
        $this->assertEquals(context_module::instance($quizobj->get_cmid()), $event->get_context());
1462
        $this->assertEventContextNotUsed($event);
1463
    }
1464
}