MDL-68619 mod_h5pactivity: add activity check to get_attempt method
[moodle.git] / mod / h5pactivity / tests / local / manager_test.php
CommitLineData
e28b4069
FR
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 * mod_h5pactivity manager tests
19 *
20 * @package mod_h5pactivity
21 * @category test
22 * @copyright 2020 Ferran Recio <ferran@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26namespace mod_h5pactivity\local;
27use context_module;
28use stdClass;
29
30/**
31 * Manager tests class for mod_h5pactivity.
32 *
33 * @package mod_h5pactivity
34 * @category test
35 * @copyright 2020 Ferran Recio <ferran@moodle.com>
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 */
38class manager_testcase extends \advanced_testcase {
39
40 /**
41 * Test for static create methods.
42 */
43 public function test_create() {
44
45 $this->resetAfterTest();
46 $this->setAdminUser();
47
48 $course = $this->getDataGenerator()->create_course();
49 $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
50 $cm = get_coursemodule_from_id('h5pactivity', $activity->cmid, 0, false, MUST_EXIST);
51 $context = context_module::instance($cm->id);
52
53 $manager = manager::create_from_instance($activity);
54 $manageractivity = $manager->get_instance();
55 $this->assertEquals($activity->id, $manageractivity->id);
56 $managercm = $manager->get_coursemodule();
57 $this->assertEquals($cm->id, $managercm->id);
58 $managercontext = $manager->get_context();
59 $this->assertEquals($context->id, $managercontext->id);
60
61 $manager = manager::create_from_coursemodule($cm);
62 $manageractivity = $manager->get_instance();
63 $this->assertEquals($activity->id, $manageractivity->id);
64 $managercm = $manager->get_coursemodule();
65 $this->assertEquals($cm->id, $managercm->id);
66 $managercontext = $manager->get_context();
67 $this->assertEquals($context->id, $managercontext->id);
68 }
69
70 /**
71 * Test for is_tracking_enabled.
72 *
73 * @dataProvider is_tracking_enabled_data
74 * @param bool $login if the user is logged in
75 * @param string $role user role in course
76 * @param int $enabletracking if tracking is enabled
77 * @param bool $expected expected result
78 */
79 public function test_is_tracking_enabled(bool $login, string $role, int $enabletracking, bool $expected) {
80
81 $this->resetAfterTest();
82 $this->setAdminUser();
83
84 $course = $this->getDataGenerator()->create_course();
85 $activity = $this->getDataGenerator()->create_module('h5pactivity',
86 ['course' => $course, 'enabletracking' => $enabletracking]);
87
88 $user = $this->getDataGenerator()->create_and_enrol($course, $role);
89 if ($login) {
90 $this->setUser($user);
91 $param = null;
92 } else {
93 $param = $user;
94 }
95
96 $manager = manager::create_from_instance($activity);
97 $this->assertEquals($expected, $manager->is_tracking_enabled($param));
98 }
99
100 /**
101 * Data provider for is_tracking_enabled.
102 *
103 * @return array
104 */
105 public function is_tracking_enabled_data(): array {
106 return [
107 'Logged student, tracking enabled' => [
108 true, 'student', 1, true
109 ],
110 'Logged student, tracking disabled' => [
111 true, 'student', 0, false
112 ],
113 'Logged teacher, tracking enabled' => [
114 true, 'editingteacher', 1, false
115 ],
116 'Logged teacher, tracking disabled' => [
117 true, 'editingteacher', 0, false
118 ],
119 'No logged student, tracking enabled' => [
120 true, 'student', 1, true
121 ],
122 'No logged student, tracking disabled' => [
123 true, 'student', 0, false
124 ],
125 'No logged teacher, tracking enabled' => [
126 true, 'editingteacher', 1, false
127 ],
128 'No logged teacher, tracking disabled' => [
129 true, 'editingteacher', 0, false
130 ],
131 ];
132 }
133
134 /**
135 * Test for get_users_scaled_score.
136 *
137 * @dataProvider get_users_scaled_score_data
138 * @param int $enabletracking if tracking is enabled
139 * @param int $gradingmethod new grading method
140 * @param array $result1 student 1 results (scaled, timemodified, attempt number)
141 * @param array $result2 student 2 results (scaled, timemodified, attempt number)
142 */
143 public function test_get_users_scaled_score(int $enabletracking, int $gradingmethod, array $result1, array $result2) {
144 global $DB;
145
146 $this->resetAfterTest();
147 $this->setAdminUser();
148
149 $course = $this->getDataGenerator()->create_course();
150 $activity = $this->getDataGenerator()->create_module('h5pactivity',
151 ['course' => $course, 'enabletracking' => $enabletracking, 'grademethod' => $gradingmethod]);
152
153 // Generate two users with 4 attempts each.
154 $user1 = $this->getDataGenerator()->create_and_enrol($course, 'student');
155 $this->generate_fake_attempts($activity, $user1, 1);
156 $user2 = $this->getDataGenerator()->create_and_enrol($course, 'student');
157 $this->generate_fake_attempts($activity, $user2, 2);
158
159 $manager = manager::create_from_instance($activity);
160
161 // Get all users scaled scores.
162 $scaleds = $manager->get_users_scaled_score();
163
164 // No results will be returned if tracking is dsabled or manual grading method is defined.
165 if (empty($result1)) {
166 $this->assertNull($scaleds);
167 return;
168 }
169
170 $this->assertCount(2, $scaleds);
171
172 // Check expected user1 scaled score.
173 $scaled = $scaleds[$user1->id];
174 $this->assertEquals($user1->id, $scaled->userid);
175 $this->assertEquals($result1[0], $scaled->scaled);
176 $this->assertEquals($result1[1], $scaled->timemodified);
177 if ($result1[2]) {
178 $attempt = $DB->get_record('h5pactivity_attempts', ['id' => $scaled->attemptid]);
179 $this->assertEquals($attempt->h5pactivityid, $activity->id);
180 $this->assertEquals($attempt->userid, $scaled->userid);
181 $this->assertEquals($attempt->scaled, round($scaled->scaled, 5));
182 $this->assertEquals($attempt->timemodified, $scaled->timemodified);
183 $this->assertEquals($result1[2], $attempt->attempt);
184 } else {
185 $this->assertEquals(0, $scaled->attemptid);
186 }
187
188 // Check expected user2 scaled score.
189 $scaled = $scaleds[$user2->id];
190 $this->assertEquals($user2->id, $scaled->userid);
191 $this->assertEquals($result2[0], round($scaled->scaled, 5));
192 $this->assertEquals($result2[1], $scaled->timemodified);
193 if ($result2[2]) {
194 $attempt = $DB->get_record('h5pactivity_attempts', ['id' => $scaled->attemptid]);
195 $this->assertEquals($attempt->h5pactivityid, $activity->id);
196 $this->assertEquals($attempt->userid, $scaled->userid);
197 $this->assertEquals($attempt->scaled, $scaled->scaled);
198 $this->assertEquals($attempt->timemodified, $scaled->timemodified);
199 $this->assertEquals($result2[2], $attempt->attempt);
200 } else {
201 $this->assertEquals(0, $scaled->attemptid);
202 }
203
204 // Now check a single user record.
205 $scaleds = $manager->get_users_scaled_score($user2->id);
206 $this->assertCount(1, $scaleds);
207 $scaled2 = $scaleds[$user2->id];
208 $this->assertEquals($scaled->userid, $scaled2->userid);
209 $this->assertEquals($scaled->scaled, $scaled2->scaled);
210 $this->assertEquals($scaled->attemptid, $scaled2->attemptid);
211 $this->assertEquals($scaled->timemodified, $scaled2->timemodified);
212 }
213
214 /**
215 * Data provider for get_users_scaled_score.
216 *
217 * @return array
218 */
219 public function get_users_scaled_score_data(): array {
220 return [
221 'Tracking with max attempt method' => [
222 1, manager::GRADEHIGHESTATTEMPT, [1.00000, 31, 2], [0.66667, 32, 2]
223 ],
224 'Tracking with average attempt method' => [
225 1, manager::GRADEAVERAGEATTEMPT, [0.61111, 51, 0], [0.52222, 52, 0]
226 ],
227 'Tracking with last attempt method' => [
228 1, manager::GRADELASTATTEMPT, [0.33333, 51, 3], [0.40000, 52, 3]
229 ],
230 'Tracking with first attempt method' => [
231 1, manager::GRADEFIRSTATTEMPT, [0.50000, 11, 1], [0.50000, 12, 1]
232 ],
233 'Tracking with manual attempt grading' => [
234 1, manager::GRADEMANUAL, [], []
235 ],
236 'No tracking with max attempt method' => [
237 0, manager::GRADEHIGHESTATTEMPT, [], []
238 ],
239 'No tracking with average attempt method' => [
240 0, manager::GRADEAVERAGEATTEMPT, [], []
241 ],
242 'No tracking with last attempt method' => [
243 0, manager::GRADELASTATTEMPT, [], []
244 ],
245 'No tracking with first attempt method' => [
246 0, manager::GRADEFIRSTATTEMPT, [], []
247 ],
248 'No tracking with manual attempt grading' => [
249 0, manager::GRADEMANUAL, [], []
250 ],
251 ];
252 }
253
254 /**
255 * Test static get_grading_methods.
256 */
257 public function test_get_grading_methods() {
258 $methods = manager::get_grading_methods();
259 $this->assertCount(5, $methods);
260 $this->assertNotEmpty($methods[manager::GRADEHIGHESTATTEMPT]);
261 $this->assertNotEmpty($methods[manager::GRADEAVERAGEATTEMPT]);
262 $this->assertNotEmpty($methods[manager::GRADELASTATTEMPT]);
263 $this->assertNotEmpty($methods[manager::GRADEFIRSTATTEMPT]);
264 $this->assertNotEmpty($methods[manager::GRADEMANUAL]);
265 }
266
9a4307dd
FR
267 /**
268 * Test static get_selected_attempt.
269 *
270 * @dataProvider get_selected_attempt_data
271 * @param int $enabletracking if tracking is enabled
272 * @param int $gradingmethod new grading method
273 * @param int $result the expected result
274 */
275 public function test_get_selected_attempt(int $enabletracking, int $gradingmethod, int $result) {
276 $this->resetAfterTest();
277 $this->setAdminUser();
278
279 $course = $this->getDataGenerator()->create_course();
280 $activity = $this->getDataGenerator()->create_module('h5pactivity',
281 ['course' => $course, 'enabletracking' => $enabletracking, 'grademethod' => $gradingmethod]);
282
283 $manager = manager::create_from_instance($activity);
284
285 $selected = $manager->get_selected_attempt();
286
287 $this->assertEquals($result, $selected[0]);
288 $this->assertNotEmpty($selected[1]);
289 }
290
291 /**
292 * Data provider for get_users_scaled_score.
293 *
294 * @return array
295 */
296 public function get_selected_attempt_data(): array {
297 return [
298 'Tracking with max attempt method' => [
299 1, manager::GRADEHIGHESTATTEMPT, manager::GRADEHIGHESTATTEMPT
300 ],
301 'Tracking with average attempt method' => [
302 1, manager::GRADEAVERAGEATTEMPT, manager::GRADEAVERAGEATTEMPT
303 ],
304 'Tracking with last attempt method' => [
305 1, manager::GRADELASTATTEMPT, manager::GRADELASTATTEMPT
306 ],
307 'Tracking with first attempt method' => [
308 1, manager::GRADEFIRSTATTEMPT, manager::GRADEFIRSTATTEMPT
309 ],
310 'Tracking with manual attempt grading' => [
311 1, manager::GRADEMANUAL, manager::GRADEMANUAL
312 ],
313 'No tracking with max attempt method' => [
314 0, manager::GRADEHIGHESTATTEMPT, manager::GRADEMANUAL
315 ],
316 'No tracking with average attempt method' => [
317 0, manager::GRADEAVERAGEATTEMPT, manager::GRADEMANUAL
318 ],
319 'No tracking with last attempt method' => [
320 0, manager::GRADELASTATTEMPT, manager::GRADEMANUAL
321 ],
322 'No tracking with first attempt method' => [
323 0, manager::GRADEFIRSTATTEMPT, manager::GRADEMANUAL
324 ],
325 'No tracking with manual attempt grading' => [
326 0, manager::GRADEMANUAL, manager::GRADEMANUAL
327 ],
328 ];
329 }
330
331 /**
332 * Test static get_review_modes.
333 */
334 public function test_get_review_modes() {
335 $methods = manager::get_review_modes();
336 $this->assertCount(2, $methods);
337 $this->assertNotEmpty($methods[manager::REVIEWCOMPLETION]);
338 $this->assertNotEmpty($methods[manager::REVIEWNONE]);
339 }
340
e28b4069
FR
341 /**
342 * Test get_grader method.
343 */
344 public function test_get_grader() {
345 $this->resetAfterTest();
346 $this->setAdminUser();
347
348 $course = $this->getDataGenerator()->create_course();
349 $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
350 $cm = get_coursemodule_from_id('h5pactivity', $activity->cmid, 0, false, MUST_EXIST);
351 $context = context_module::instance($cm->id);
352
353 $manager = manager::create_from_instance($activity);
354 $grader = $manager->get_grader();
355
356 $this->assertInstanceOf('mod_h5pactivity\local\grader', $grader);
357 }
358
9a4307dd
FR
359
360 /**
361 * Test static can_view_all_attempts.
362 *
363 * @dataProvider can_view_all_attempts_data
364 * @param int $enabletracking if tracking is enabled
365 * @param bool $usestudent if test must be done with a user role
366 * @param bool $useloggedin if test must be done with the loggedin user
367 * @param bool $result the expected result
368 */
369 public function test_can_view_all_attempts(int $enabletracking, bool $usestudent, bool $useloggedin, bool $result) {
370 global $USER;
371
372 $this->resetAfterTest();
373 $this->setAdminUser();
374
375 $course = $this->getDataGenerator()->create_course();
376 $activity = $this->getDataGenerator()->create_module('h5pactivity',
377 ['course' => $course, 'enabletracking' => $enabletracking]);
378
379 $manager = manager::create_from_instance($activity);
380
381 $user = $this->getDataGenerator()->create_and_enrol($course, 'student');
382 $loggedin = $USER;
383
384 // We want to test what when the method is called to check a different user than $USER.
385 if (!$usestudent) {
386 $loggedin = $user;
387 $user = $USER;
388 }
389
390 if ($useloggedin) {
391 $this->setUser($user);
392 $user = null;
393 } else {
394 $this->setUser($loggedin);
395 }
396
397 $this->assertEquals($result, $manager->can_view_all_attempts($user));
398 }
399
400 /**
401 * Data provider for test_can_view_all_attempts.
402 *
403 * @return array
404 */
405 public function can_view_all_attempts_data(): array {
406 return [
407 // No tracking cases.
408 'No tracking with admin using $USER' => [
409 0, false, false, false
410 ],
411 'No tracking with student using $USER' => [
412 0, true, false, false
413 ],
414 'No tracking with admin loggedin' => [
415 0, false, true, false
416 ],
417 'No tracking with student loggedin' => [
418 0, true, true, false
419 ],
420 // Tracking enabled cases.
421 'Tracking with admin using $USER' => [
422 1, false, false, true
423 ],
424 'Tracking with student using $USER' => [
425 1, true, false, false
426 ],
427 'Tracking with admin loggedin' => [
428 1, false, true, true
429 ],
430 'Tracking with student loggedin' => [
431 1, true, true, false
432 ],
433 ];
434 }
435
436 /**
437 * Test static can_view_own_attempts.
438 *
439 * @dataProvider can_view_own_attempts_data
440 * @param int $enabletracking if tracking is enabled
441 * @param int $reviewmode the attempt review mode
442 * @param bool $useloggedin if test must be done with the loggedin user
443 * @param bool $hasattempts if the student have attempts
444 * @param bool $result the expected result
445 */
446 public function test_can_view_own_attempts(int $enabletracking, int $reviewmode,
447 bool $useloggedin, bool $hasattempts, bool $result) {
448
449 $this->resetAfterTest();
450 $this->setAdminUser();
451
452 $course = $this->getDataGenerator()->create_course();
453 $activity = $this->getDataGenerator()->create_module('h5pactivity',
454 ['course' => $course, 'enabletracking' => $enabletracking, 'reviewmode' => $reviewmode]);
455
456 $manager = manager::create_from_instance($activity);
457
458 $user = $this->getDataGenerator()->create_and_enrol($course, 'student');
459
460 if ($hasattempts) {
461 $this->generate_fake_attempts($activity, $user, 1);
462 }
463
464 if ($useloggedin) {
465 $this->setUser($user);
466 $user = null;
467 }
468
469 $this->assertEquals($result, $manager->can_view_own_attempts($user));
470 }
471
472 /**
473 * Data provider for test_can_view_own_attempts.
474 *
475 * @return array
476 */
477 public function can_view_own_attempts_data(): array {
478 return [
479 // No tracking cases.
480 'No tracking, review none, using $USER, without attempts' => [
481 0, manager::REVIEWNONE, false, false, false
482 ],
483 'No tracking, review enabled, using $USER, without attempts' => [
484 0, manager::REVIEWCOMPLETION, false, false, false
485 ],
486 'No tracking, review none, loggedin, without attempts' => [
487 0, manager::REVIEWNONE, true, false, false
488 ],
489 'No tracking, review enabled, loggedin, without attempts' => [
490 0, manager::REVIEWCOMPLETION, true, false, false
491 ],
492 'No tracking, review none, using $USER, with attempts' => [
493 0, manager::REVIEWNONE, false, true, false
494 ],
495 'No tracking, review enabled, using $USER, with attempts' => [
496 0, manager::REVIEWCOMPLETION, false, true, false
497 ],
498 'No tracking, review none, loggedin, with attempts' => [
499 0, manager::REVIEWNONE, true, true, false
500 ],
501 'No tracking, review enabled, loggedin, with attempts' => [
502 0, manager::REVIEWCOMPLETION, true, true, false
503 ],
504 // Tracking enabled cases.
505 'Tracking enabled, review none, using $USER, without attempts' => [
506 1, manager::REVIEWNONE, false, false, false
507 ],
508 'Tracking enabled, review enabled, using $USER, without attempts' => [
509 1, manager::REVIEWCOMPLETION, false, false, true
510 ],
511 'Tracking enabled, review none, loggedin, without attempts' => [
512 1, manager::REVIEWNONE, true, false, false
513 ],
514 'Tracking enabled, review enabled, loggedin, without attempts' => [
515 1, manager::REVIEWCOMPLETION, true, false, true
516 ],
517 'Tracking enabled, review none, using $USER, with attempts' => [
518 1, manager::REVIEWNONE, false, true, false
519 ],
520 'Tracking enabled, review enabled, using $USER, with attempts' => [
521 1, manager::REVIEWCOMPLETION, false, true, true
522 ],
523 'Tracking enabled, review none, loggedin, with attempts' => [
524 1, manager::REVIEWNONE, true, true, false
525 ],
526 'Tracking enabled, review enabled, loggedin, with attempts' => [
527 1, manager::REVIEWCOMPLETION, true, true, true
528 ],
529 ];
530 }
531
532 /**
533 * Test static count_attempts.
534 */
535 public function test_count_attempts() {
536
537 $this->resetAfterTest();
538 $this->setAdminUser();
539
540 $course = $this->getDataGenerator()->create_course();
541 $activity = $this->getDataGenerator()->create_module('h5pactivity',
542 ['course' => $course]);
543
544 $manager = manager::create_from_instance($activity);
545
546 // User without attempts.
547 $user1 = $this->getDataGenerator()->create_and_enrol($course, 'student');
548
549 // User with 1 attempt.
550 $user2 = $this->getDataGenerator()->create_and_enrol($course, 'student');
551 $this->generate_fake_attempts($activity, $user2, 1);
552
553 // User with 2 attempts.
554 $user3 = $this->getDataGenerator()->create_and_enrol($course, 'student');
555 $this->generate_fake_attempts($activity, $user3, 1);
556
557 // Incomplete user2 and 3 has only 3 attempts completed.
558 $this->assertEquals(0, $manager->count_attempts($user1->id));
559 $this->assertEquals(3, $manager->count_attempts($user2->id));
560 $this->assertEquals(3, $manager->count_attempts($user3->id));
561 }
562
563 /**
564 * Test static count_attempts.
565 */
566 public function test_count_users_attempts() {
567
568 $this->resetAfterTest();
569 $this->setAdminUser();
570
571 $course = $this->getDataGenerator()->create_course();
572 $activity = $this->getDataGenerator()->create_module('h5pactivity',
573 ['course' => $course]);
574
575 $manager = manager::create_from_instance($activity);
576
577 // User without attempts.
578 $user1 = $this->getDataGenerator()->create_and_enrol($course, 'student');
579
580 // User with 1 attempt.
581 $user2 = $this->getDataGenerator()->create_and_enrol($course, 'student');
582 $this->generate_fake_attempts($activity, $user2, 1);
583
584 // User with 2 attempts.
585 $user3 = $this->getDataGenerator()->create_and_enrol($course, 'student');
586 $this->generate_fake_attempts($activity, $user3, 1);
587
588 $attempts = $manager->count_users_attempts();
589 $this->assertArrayNotHasKey($user1->id, $attempts);
590 $this->assertArrayHasKey($user2->id, $attempts);
591 $this->assertEquals(4, $attempts[$user2->id]);
592 $this->assertArrayHasKey($user3->id, $attempts);
593 $this->assertEquals(4, $attempts[$user3->id]);
594 }
595
596 /**
597 * Test static get_report.
598 *
599 * @dataProvider get_report_data
600 * @param int $enabletracking if tracking is enabled
601 * @param int $reviewmode the attempt review mode
602 * @param bool $createattempts if the student have attempts
603 * @param string $role the user role (student or editingteacher)
604 * @param array $results the expected classname (or null)
605 */
606 public function test_get_report(int $enabletracking, int $reviewmode, bool $createattempts,
607 string $role, array $results) {
608
609 $this->resetAfterTest();
610 $this->setAdminUser();
611
612 $course = $this->getDataGenerator()->create_course();
613 $activity = $this->getDataGenerator()->create_module('h5pactivity',
614 ['course' => $course, 'enabletracking' => $enabletracking, 'reviewmode' => $reviewmode]);
615
616 $manager = manager::create_from_instance($activity);
617 $cm = get_coursemodule_from_id('h5pactivity', $activity->cmid, 0, false, MUST_EXIST);
618
619 $users = [
620 'editingteacher' => $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'),
621 'student' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
622 'otheruser' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
623 ];
624
625 $attempts = [];
626 if ($createattempts) {
627 $this->generate_fake_attempts($activity, $users['student'], 1);
628 $this->generate_fake_attempts($activity, $users['otheruser'], 2);
629 $attempts['student'] = attempt::last_attempt($users['student'], $cm);
630 $attempts['otheruser'] = attempt::last_attempt($users['otheruser'], $cm);
631 }
632
633 $classnamebase = 'mod_h5pactivity\\local\\report\\';
634
635 $attemptid = null;
636 if (isset($attempts['student'])) {
637 $attemptid = $attempts['student']->get_id() ?? null;
638 }
639 $userid = $users['student']->id;
640
641 // Check reports.
642 $this->setUser($users[$role]);
643
644 $report = $manager->get_report(null, null);
645 if ($results[0] === null) {
646 $this->assertNull($report);
647 } else {
648 $this->assertEquals($classnamebase.$results[0], get_class($report));
649 }
650
651 $report = $manager->get_report($userid, null);
652 if ($results[1] === null) {
653 $this->assertNull($report);
654 } else {
655 $this->assertEquals($classnamebase.$results[1], get_class($report));
656 }
657
658 $report = $manager->get_report($userid, $attemptid);
659 if ($results[2] === null) {
660 $this->assertNull($report);
661 } else {
662 $this->assertEquals($classnamebase.$results[2], get_class($report));
663 }
664
665 // Check that student cannot access another student reports.
666 if ($role == 'student') {
667 $attemptid = null;
668 if (isset($attempts['otheruser'])) {
669 $attemptid = $attempts['otheruser']->get_id() ?? null;
670 }
671 $userid = $users['otheruser']->id;
672
673 $report = $manager->get_report($userid, null);
674 $this->assertNull($report);
675
676 $report = $manager->get_report($userid, $attemptid);
677 $this->assertNull($report);
678 }
679 }
680
681 /**
682 * Data provider for test_get_report.
683 *
684 * @return array
685 */
686 public function get_report_data(): array {
687 return [
688 // No tracking scenarios.
689 'No tracking, review none, no attempts, teacher' => [
690 0, manager::REVIEWNONE, false, 'editingteacher', [null, null, null]
691 ],
692 'No tracking, review own, no attempts, teacher' => [
693 0, manager::REVIEWCOMPLETION, false, 'editingteacher', [null, null, null]
694 ],
695 'No tracking, review none, no attempts, student' => [
696 0, manager::REVIEWNONE, false, 'student', [null, null, null]
697 ],
698 'No tracking, review own, no attempts, student' => [
699 0, manager::REVIEWCOMPLETION, false, 'student', [null, null, null]
700 ],
701 'No tracking, review none, with attempts, teacher' => [
702 0, manager::REVIEWNONE, true, 'editingteacher', [null, null, null]
703 ],
704 'No tracking, review own, with attempts, teacher' => [
705 0, manager::REVIEWCOMPLETION, true, 'editingteacher', [null, null, null]
706 ],
707 'No tracking, review none, with attempts, student' => [
708 0, manager::REVIEWNONE, true, 'student', [null, null, null]
709 ],
710 'No tracking, review own, with attempts, student' => [
711 0, manager::REVIEWCOMPLETION, true, 'student', [null, null, null]
712 ],
713 // Tracking enabled scenarios.
714 'Tracking enabled, review none, no attempts, teacher' => [
715 1, manager::REVIEWNONE, false, 'editingteacher', ['participants', 'attempts', 'attempts']
716 ],
717 'Tracking enabled, review own, no attempts, teacher' => [
718 1, manager::REVIEWCOMPLETION, false, 'editingteacher', ['participants', 'attempts', 'attempts']
719 ],
720 'Tracking enabled, review none, no attempts, student' => [
721 1, manager::REVIEWNONE, false, 'student', [null, null, null]
722 ],
723 'Tracking enabled, review own, no attempts, student' => [
724 1, manager::REVIEWCOMPLETION, false, 'student', ['attempts', 'attempts', 'attempts']
725 ],
726 'Tracking enabled, review none, with attempts, teacher' => [
727 1, manager::REVIEWNONE, true, 'editingteacher', ['participants', 'attempts', 'results']
728 ],
729 'Tracking enabled, review own, with attempts, teacher' => [
730 1, manager::REVIEWCOMPLETION, true, 'editingteacher', ['participants', 'attempts', 'results']
731 ],
732 'Tracking enabled, review none, with attempts, student' => [
733 1, manager::REVIEWNONE, true, 'student', [null, null, null]
734 ],
735 'Tracking enabled, review own, with attempts, student' => [
736 1, manager::REVIEWCOMPLETION, true, 'student', ['attempts', 'attempts', 'results']
737 ],
738 ];
739 }
740
42c48b66
FR
741 /**
742 * Test get_attempt method.
743 *
744 * @dataProvider get_attempt_data
745 * @param string $attemptname the attempt to use
746 * @param string|null $result the expected attempt ID or null for none
747 */
748 public function test_get_attempt(string $attemptname, ?string $result): void {
749
750 $this->resetAfterTest();
751 $this->setAdminUser();
752
753 $course = $this->getDataGenerator()->create_course();
754
755 $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
756 $cm = get_coursemodule_from_id('h5pactivity', $activity->cmid, 0, false, MUST_EXIST);
757
758 $otheractivity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
759 $othercm = get_coursemodule_from_id('h5pactivity', $otheractivity->cmid, 0, false, MUST_EXIST);
760
761 $manager = manager::create_from_instance($activity);
762
763 $user = $this->getDataGenerator()->create_and_enrol($course, 'student');
764
765 $attempts = ['inexistent' => 0];
766
767 $this->generate_fake_attempts($activity, $user, 1);
768 $attempt = attempt::last_attempt($user, $cm);
769 $attempts['current'] = $attempt->get_id();
770
771 $this->generate_fake_attempts($otheractivity, $user, 1);
772 $attempt = attempt::last_attempt($user, $othercm);
773 $attempts['other'] = $attempt->get_id();
774
775 $attempt = $manager->get_attempt($attempts[$attemptname]);
776 if ($result === null) {
777 $this->assertNull($attempt);
778 } else {
779 $this->assertEquals($attempts[$attemptname], $attempt->get_id());
780 $this->assertEquals($activity->id, $attempt->get_h5pactivityid());
781 $this->assertEquals($user->id, $attempt->get_userid());
782 $this->assertEquals(4, $attempt->get_attempt());
783 }
784 }
785
786 /**
787 * Data provider for test_get_attempt.
788 *
789 * @return array
790 */
791 public function get_attempt_data(): array {
792 return [
793 'Get the current activity attempt' => [
794 'current', 'current'
795 ],
796 'Try to get another activity attempt' => [
797 'other', null
798 ],
799 'Try to get an inexistent attempt' => [
800 'inexistent', null
801 ],
802 ];
803 }
804
e28b4069
FR
805 /**
806 * Insert fake attempt data into h5pactiviyt_attempts.
807 *
808 * This function insert 4 attempts. 3 of them finished with different gradings
809 * and timestamps and 1 unfinished.
810 *
811 * @param stdClass $activity the activity record
812 * @param stdClass $user user record
813 * @param int $basescore a score to be used to generate all attempts
814 */
815 private function generate_fake_attempts(stdClass $activity, stdClass $user, int $basescore) {
816 global $DB;
817
818 $attempt = (object)[
819 'h5pactivityid' => $activity->id,
820 'userid' => $user->id,
821 'timecreated' => $basescore,
822 'timemodified' => ($basescore + 10),
823 'attempt' => 1,
824 'rawscore' => $basescore,
825 'maxscore' => ($basescore + $basescore),
826 'duration' => $basescore,
827 'completion' => 1,
828 'success' => 1,
829 ];
830 $attempt->scaled = $attempt->rawscore / $attempt->maxscore;
831 $DB->insert_record('h5pactivity_attempts', $attempt);
832
833 $attempt = (object)[
834 'h5pactivityid' => $activity->id,
835 'userid' => $user->id,
836 'timecreated' => ($basescore + 20),
837 'timemodified' => ($basescore + 30),
838 'attempt' => 2,
839 'rawscore' => $basescore,
840 'maxscore' => ($basescore + $basescore - 1),
841 'duration' => $basescore,
842 'completion' => 1,
843 'success' => 1,
844 ];
845 $attempt->scaled = $attempt->rawscore / $attempt->maxscore;
846 $DB->insert_record('h5pactivity_attempts', $attempt);
847
848 $attempt = (object)[
849 'h5pactivityid' => $activity->id,
850 'userid' => $user->id,
851 'timecreated' => ($basescore + 40),
852 'timemodified' => ($basescore + 50),
853 'attempt' => 3,
854 'rawscore' => $basescore,
855 'maxscore' => ($basescore + $basescore + 1),
856 'duration' => $basescore,
857 'completion' => 1,
858 'success' => 0,
859 ];
860 $attempt->scaled = $attempt->rawscore / $attempt->maxscore;
861 $DB->insert_record('h5pactivity_attempts', $attempt);
862
863 // Unfinished attempt.
864 $attempt = (object)[
865 'h5pactivityid' => $activity->id,
866 'userid' => $user->id,
867 'timecreated' => ($basescore + 60),
868 'timemodified' => ($basescore + 60),
869 'attempt' => 4,
870 'rawscore' => $basescore,
871 'maxscore' => $basescore,
872 'duration' => $basescore,
873 ];
874 $DB->insert_record('h5pactivity_attempts', $attempt);
875 }
876}