Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | 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
namespace mod_h5pactivity;
19
 
20
use advanced_testcase;
21
use mod_h5pactivity\local\manager;
22
 
23
/**
24
 * Unit tests for (some of) mod/h5pactivity/lib.php.
25
 *
26
 * @package    mod_h5pactivity
27
 * @copyright  2021 Ilya Tregubov <ilya@moodle.com>
28
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29
 */
30
class lib_test extends advanced_testcase {
31
 
32
    /**
33
     * Load required test libraries
34
     */
35
    public static function setUpBeforeClass(): void {
36
        global $CFG;
37
        require_once("{$CFG->dirroot}/mod/h5pactivity/lib.php");
38
    }
39
 
40
    /**
41
     * Test that h5pactivity_delete_instance removes data.
42
     *
43
     * @covers ::h5pactivity_delete_instance
44
     */
45
    public function test_h5pactivity_delete_instance() {
46
        global $DB;
47
        $this->resetAfterTest();
48
        $this->setAdminUser();
49
 
50
        $course = $this->getDataGenerator()->create_course();
51
        $user = $this->getDataGenerator()->create_and_enrol($course, 'student');
52
        $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
53
        $this->setUser($user);
54
 
55
        /** @var \mod_h5pactivity_generator $generator */
56
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
57
 
58
        /** @var \core_h5p_generator $h5pgenerator */
59
        $h5pgenerator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
60
 
61
        // Add an attempt to the H5P activity.
62
        $attemptinfo = [
63
            'userid' => $user->id,
64
            'h5pactivityid' => $activity->id,
65
            'attempt' => 1,
66
            'interactiontype' => 'compound',
67
            'rawscore' => 2,
68
            'maxscore' => 2,
69
            'duration' => 1,
70
            'completion' => 1,
71
            'success' => 0,
72
        ];
73
        $generator->create_attempt($attemptinfo);
74
 
75
        // Add also a xAPI state to the H5P activity.
76
        $filerecord = [
77
            'contextid' => \context_module::instance($activity->cmid)->id,
78
            'component' => 'mod_h5pactivity',
79
            'filearea' => 'package',
80
            'itemid' => 0,
81
            'filepath' => '/',
82
            'filepath' => '/',
83
            'filename' => 'dummy.h5p',
84
            'addxapistate' => true,
85
        ];
86
        $h5pgenerator->generate_h5p_data(false, $filerecord);
87
 
88
        // Check the H5P activity exists and the attempt has been created.
89
        $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id]));
90
        $this->assertEquals(2, $DB->count_records('grade_items'));
91
        $this->assertEquals(2, $DB->count_records('grade_grades'));
92
        $this->assertEquals(1, $DB->count_records('xapi_states'));
93
 
94
        // Check nothing happens when given activity id doesn't exist.
95
        h5pactivity_delete_instance($activity->id + 1);
96
        $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id]));
97
        $this->assertEquals(2, $DB->count_records('grade_items'));
98
        $this->assertEquals(2, $DB->count_records('grade_grades'));
99
        $this->assertEquals(1, $DB->count_records('xapi_states'));
100
 
101
        // Check the H5P instance and its associated data is removed.
102
        h5pactivity_delete_instance($activity->id);
103
        $this->assertEmpty($DB->get_record('h5pactivity', ['id' => $activity->id]));
104
        $this->assertEquals(1, $DB->count_records('grade_items'));
105
        $this->assertEquals(1, $DB->count_records('grade_grades'));
106
        $this->assertEquals(0, $DB->count_records('xapi_states'));
107
    }
108
 
109
    /**
110
     * Test that assign_print_recent_activity shows ungraded submitted assignments.
111
     *
112
     * @covers ::h5pactivity_print_recent_activity
113
     */
114
    public function test_print_recent_activity() {
115
        $this->resetAfterTest();
116
        $this->setAdminUser();
117
 
118
        $course = $this->getDataGenerator()->create_course();
119
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
120
        $activity = $this->getDataGenerator()->create_module('h5pactivity',
121
            ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]);
122
 
123
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
124
 
125
        $manager = manager::create_from_instance($activity);
126
        $cm = $manager->get_coursemodule();
127
 
128
        $user = $student;
129
        $params = ['cmid' => $cm->id, 'userid' => $user->id];
130
        $generator->create_content($activity, $params);
131
        $this->setUser($student);
132
        $this->expectOutputRegex('/submitted:/');
133
        h5pactivity_print_recent_activity($course, true, time() - 3600);
134
    }
135
 
136
    /**
137
     * Test that h5pactivity_print_recent_activity does not display any warnings when a custom fullname has been configured.
138
     *
139
     * @covers ::h5pactivity_print_recent_activity
140
     */
141
    public function test_print_recent_activity_fullname() {
142
        $this->resetAfterTest();
143
        $this->setAdminUser();
144
 
145
        $course = $this->getDataGenerator()->create_course();
146
        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
147
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
148
        $activity = $this->getDataGenerator()->create_module('h5pactivity',
149
            ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]);
150
 
151
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
152
 
153
        $manager = manager::create_from_instance($activity);
154
        $cm = $manager->get_coursemodule();
155
 
156
        $user = $student;
157
        $params = ['cmid' => $cm->id, 'userid' => $user->id];
158
        $generator->create_content($activity, $params);
159
 
160
        $this->setUser($teacher);
161
 
162
        $this->expectOutputRegex('/submitted:/');
163
        set_config('fullnamedisplay', 'firstname, lastnamephonetic');
164
        h5pactivity_print_recent_activity($course, false, time() - 3600);
165
    }
166
 
167
    /**
168
     * Test that h5pactivity_get_recent_mod_activity fetches the h5pactivity correctly.
169
     *
170
     * @covers ::h5pactivity_get_recent_mod_activity
171
     */
172
    public function test_h5pactivity_get_recent_mod_activity() {
173
        $this->resetAfterTest();
174
        $this->setAdminUser();
175
 
176
        $course = $this->getDataGenerator()->create_course();
177
        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
178
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
179
        $activity = $this->getDataGenerator()->create_module('h5pactivity',
180
            ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]);
181
 
182
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
183
 
184
        $manager = manager::create_from_instance($activity);
185
        $cm = $manager->get_coursemodule();
186
 
187
        $user = $student;
188
        $params = ['cmid' => $cm->id, 'userid' => $user->id];
189
        $generator->create_content($activity, $params);
190
 
191
        $index = 1;
192
        $activities = [
193
            $index => (object) [
194
                'type' => 'h5pactivity',
195
                'cmid' => $cm->id,
196
            ],
197
        ];
198
 
199
        $this->setUser($teacher);
200
        h5pactivity_get_recent_mod_activity($activities, $index, time() - HOURSECS, $course->id, $cm->id);
201
 
202
        $activity = $activities[1];
203
        $this->assertEquals("h5pactivity", $activity->type);
204
        $this->assertEquals($student->id, $activity->user->id);
205
    }
206
 
207
    /**
208
     * Test that h5pactivity_get_recent_mod_activity fetches activity correctly.
209
     *
210
     * @covers ::h5pactivity_fetch_recent_activity
211
     */
212
    public function test_h5pactivity_fetch_recent_activity() {
213
        global $DB;
214
 
215
        $this->resetAfterTest();
216
        $this->setAdminUser();
217
 
218
        $course = $this->getDataGenerator()->create_course();
219
 
220
        // Create users and groups.
221
        $students = array();
222
        $groups = array();
223
        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
224
 
225
        for ($i = 1; $i < 6; $i++) {
226
            $students[$i] = $this->getDataGenerator()->create_and_enrol($course, 'student');
227
            $groups[$i] = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
228
        }
229
        $groups[$i] = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'participation' => 0));
230
 
231
        // Update the course set the groupmode SEPARATEGROUPS and forced.
232
        update_course((object)array('id' => $course->id, 'groupmode' => SEPARATEGROUPS, 'groupmodeforce' => true));
233
 
234
        // Student 1 is in groups 1 and 3.
235
        groups_add_member($groups[1], $students[1]);
236
        groups_add_member($groups[3], $students[1]);
237
 
238
        // Student 2 is in groups 1 and 2.
239
        groups_add_member($groups[1], $students[2]);
240
        groups_add_member($groups[2], $students[2]);
241
 
242
        // Student 3 is only in group 3.
243
        groups_add_member($groups[3], $students[3]);
244
 
245
        // Student 4 is only in group 5 (non-participation).
246
        groups_add_member($groups[6], $students[4]);
247
 
248
        // Student 5 is not in any groups.
249
 
250
        // Grader is only in group 3.
251
        groups_add_member($groups[3], $teacher);
252
 
253
        $timestart = time() - 1;
254
        // Create h5pactivity.
255
        $activity = $this->getDataGenerator()->create_module('h5pactivity',
256
            ['course' => $course->id, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT,
257
                'groupmode' => SEPARATEGROUPS]);
258
 
259
        $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
260
        $cmcontext = \context_module::instance($activity->cmid);
261
        assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $cmcontext, true);
262
 
263
        $manager = manager::create_from_instance($activity);
264
        $cm = $manager->get_coursemodule();
265
 
266
        // Create attempts.
267
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
268
        foreach ($students as $student) {
269
            $params = ['cmid' => $cm->id, 'userid' => $student->id];
270
            $generator->create_content($activity, $params);
271
        }
272
 
273
        // Get all attempts.
274
        $dbparams = [$timestart, $course->id, 'h5pactivity'];
275
        $userfieldsapi = \core_user\fields::for_userpic();
276
        $namefields = $userfieldsapi->get_sql('u', false, '', 'userid', false)->selects;;
277
 
278
        $sql = "SELECT h5pa.id, h5pa.timemodified, cm.id as cmid, $namefields
279
                  FROM {h5pactivity_attempts} h5pa
280
                  JOIN {h5pactivity} h5p      ON h5p.id = h5pa.h5pactivityid
281
                  JOIN {course_modules} cm ON cm.instance = h5p.id
282
                  JOIN {modules} md        ON md.id = cm.module
283
                  JOIN {user} u            ON u.id = h5pa.userid
284
                 WHERE h5pa.timemodified > ?
285
                   AND h5p.course = ?
286
                   AND md.name = ?
287
              ORDER BY h5pa.timemodified ASC";
288
 
289
        $submissions = $DB->get_records_sql($sql, $dbparams);
290
        $this->assertCount(count($students), $submissions);
291
 
292
        // Fetch activity for student (only his own).
293
        $this->setUser($students[1]);
294
        $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id);
295
        $this->assertCount(1, $recentactivity);
296
        $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid);
297
 
298
        // Fetch users group info for grader.
299
        $this->setUser($teacher);
300
        $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id);
301
        $this->assertCount(2, $recentactivity);
302
        // Grader, Student 1 and 3 are in Group 3.
303
        $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid);
304
        $this->assertEquals($students[3]->id, $recentactivity[$students[3]->id]->userid);
305
 
306
        // Grader is in Group 2.
307
        groups_remove_member($groups[3], $teacher);
308
        groups_add_member($groups[2], $teacher);
309
        get_fast_modinfo($course->id, 0, true);
310
        $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id);
311
        $this->assertCount(1, $recentactivity);
312
        // Grader, Student 2 are in Group 2.
313
        $this->assertEquals($students[2]->id, $recentactivity[$students[2]->id]->userid);
314
 
315
        // Grader is in Group 1.
316
        groups_remove_member($groups[2], $teacher);
317
        groups_add_member($groups[1], $teacher);
318
        get_fast_modinfo($course->id, 0, true);
319
        $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id);
320
        $this->assertCount(2, $recentactivity);
321
        // Grader, Student 1 and 2 are in Group 1.
322
        $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid);
323
        $this->assertEquals($students[2]->id, $recentactivity[$students[2]->id]->userid);
324
 
325
        // Grader is in no group.
326
        groups_remove_member($groups[1], $teacher);
327
        get_fast_modinfo($course->id, 0, true);
328
        $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id);
329
        // Student 4 and Student 5 have submissions, but they are not in a participation group, so they do not show up in recent
330
        // activity for separate groups mode.
331
        $this->assertCount(0, $recentactivity);
332
    }
333
 
334
    /**
335
     * Test that h5pactivity_reset_userdata reset user data.
336
     *
337
     * @covers ::h5pactivity_reset_userdata
338
     */
339
    public function test_h5pactivity_reset_userdata() {
340
        global $DB;
341
        $this->resetAfterTest();
342
        $this->setAdminUser();
343
 
344
        $course = $this->getDataGenerator()->create_course();
345
        $user = $this->getDataGenerator()->create_and_enrol($course, 'student');
346
        $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
347
        $this->setUser($user);
348
 
349
        /** @var \mod_h5pactivity_generator $generator */
350
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity');
351
 
352
        /** @var \core_h5p_generator $h5pgenerator */
353
        $h5pgenerator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
354
 
355
        // Add an attempt to the H5P activity.
356
        $attemptinfo = [
357
            'userid' => $user->id,
358
            'h5pactivityid' => $activity->id,
359
            'attempt' => 1,
360
            'interactiontype' => 'compound',
361
            'rawscore' => 2,
362
            'maxscore' => 2,
363
            'duration' => 1,
364
            'completion' => 1,
365
            'success' => 0,
366
        ];
367
        $generator->create_attempt($attemptinfo);
368
 
369
        // Add also a xAPI state to the H5P activity.
370
        $filerecord = [
371
            'contextid' => \context_module::instance($activity->cmid)->id,
372
            'component' => 'mod_h5pactivity',
373
            'filearea' => 'package',
374
            'itemid' => 0,
375
            'filepath' => '/',
376
            'filepath' => '/',
377
            'filename' => 'dummy.h5p',
378
            'addxapistate' => true,
379
        ];
380
        $h5pgenerator->generate_h5p_data(false, $filerecord);
381
 
382
        // Check the H5P activity exists and the attempt has been created with the expected data.
383
        $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id]));
384
        $this->assertEquals(2, $DB->count_records('grade_items'));
385
        $this->assertEquals(2, $DB->count_records('grade_grades'));
386
        $this->assertEquals(1, $DB->count_records('xapi_states'));
387
 
388
        // Check nothing happens when reset_h5pactivity is not set.
389
        $data = new \stdClass();
390
        h5pactivity_reset_userdata($data);
391
        $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id]));
392
        $this->assertEquals(2, $DB->count_records('grade_items'));
393
        $this->assertEquals(2, $DB->count_records('grade_grades'));
394
        $this->assertEquals(1, $DB->count_records('xapi_states'));
395
        $this->assertEquals(1, $DB->count_records('xapi_states'));
396
 
397
        // Check nothing happens when reset_h5pactivity is not set.
398
        $data = (object) [
399
            'courseid' => $course->id,
400
        ];
401
        h5pactivity_reset_userdata($data);
402
        $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id]));
403
        $this->assertEquals(2, $DB->count_records('grade_items'));
404
        $this->assertEquals(2, $DB->count_records('grade_grades'));
405
        $this->assertEquals(1, $DB->count_records('xapi_states'));
406
        $this->assertEquals(1, $DB->count_records('xapi_states'));
407
 
408
        // Check nothing happens when the given course doesn't exist.
409
        $data = (object) [
410
            'reset_h5pactivity' => true,
411
            'courseid' => $course->id + 1,
412
        ];
413
        h5pactivity_reset_userdata($data);
414
        $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id]));
415
        $this->assertEquals(2, $DB->count_records('grade_items'));
416
        $this->assertEquals(2, $DB->count_records('grade_grades'));
417
        $this->assertEquals(1, $DB->count_records('xapi_states'));
418
        $this->assertEquals(1, $DB->count_records('xapi_states'));
419
 
420
        // Check the H5P instance and its associated data is reset.
421
        $data = (object) [
422
            'reset_h5pactivity' => true,
423
            'courseid' => $course->id,
424
        ];
425
        h5pactivity_reset_userdata($data);
426
        $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id]));
427
        $this->assertEquals(2, $DB->count_records('grade_items'));
428
        $this->assertEquals(1, $DB->count_records('grade_grades'));
429
        $this->assertEquals(0, $DB->count_records('xapi_states'));
430
    }
431
}