Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.


namespace mod_h5pactivity;

use advanced_testcase;
use mod_h5pactivity\local\manager;

/**
 * Unit tests for (some of) mod/h5pactivity/lib.php.
 *
> * @package mod_h5pactivity
* @copyright 2021 Ilya Tregubov <ilya@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class lib_test extends advanced_testcase { /** * Load required test libraries */ public static function setUpBeforeClass(): void { global $CFG; require_once("{$CFG->dirroot}/mod/h5pactivity/lib.php"); } /**
> * Test that h5pactivity_delete_instance removes data. * Test that assign_print_recent_activity shows ungraded submitted assignments. > * * > * @covers ::h5pactivity_delete_instance * @covers ::h5pactivity_print_recent_activity > */ */ > public function test_h5pactivity_delete_instance() { public function test_print_recent_activity() { > global $DB; $this->resetAfterTest(); > $this->resetAfterTest(); $this->setAdminUser(); > $this->setAdminUser(); > $course = $this->getDataGenerator()->create_course(); > $course = $this->getDataGenerator()->create_course(); $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); > $user = $this->getDataGenerator()->create_and_enrol($course, 'student'); $activity = $this->getDataGenerator()->create_module('h5pactivity', > $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]); ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]); > $this->setUser($user); > $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); > /** @var \mod_h5pactivity_generator $generator */ > $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); $manager = manager::create_from_instance($activity); > $cm = $manager->get_coursemodule(); > /** @var \core_h5p_generator $h5pgenerator */ > $h5pgenerator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $user = $student; > $params = ['cmid' => $cm->id, 'userid' => $user->id]; > // Add an attempt to the H5P activity. $generator->create_content($activity, $params); > $attemptinfo = [ $this->setUser($student); > 'userid' => $user->id, $this->expectOutputRegex('/submitted:/'); > 'h5pactivityid' => $activity->id, h5pactivity_print_recent_activity($course, true, time() - 3600); > 'attempt' => 1, } > 'interactiontype' => 'compound', > 'rawscore' => 2, /** > 'maxscore' => 2, * Test that h5pactivity_print_recent_activity does not display any warnings when a custom fullname has been configured. > 'duration' => 1, * > 'completion' => 1, * @covers ::h5pactivity_print_recent_activity > 'success' => 0, */ > ]; public function test_print_recent_activity_fullname() { > $generator->create_attempt($attemptinfo); $this->resetAfterTest(); > $this->setAdminUser(); > // Add also a xAPI state to the H5P activity. > $filerecord = [ $course = $this->getDataGenerator()->create_course(); > 'contextid' => \context_module::instance($activity->cmid)->id, $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); > 'component' => 'mod_h5pactivity', $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); > 'filearea' => 'package', $activity = $this->getDataGenerator()->create_module('h5pactivity', > 'itemid' => 0, ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]); > 'filepath' => '/', > 'filepath' => '/', $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); > 'filename' => 'dummy.h5p', > 'addxapistate' => true, $manager = manager::create_from_instance($activity); > ]; $cm = $manager->get_coursemodule(); > $h5pgenerator->generate_h5p_data(false, $filerecord); > $user = $student; > // Check the H5P activity exists and the attempt has been created. $params = ['cmid' => $cm->id, 'userid' => $user->id]; > $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id])); $generator->create_content($activity, $params); > $this->assertEquals(2, $DB->count_records('grade_items')); > $this->assertEquals(2, $DB->count_records('grade_grades')); $this->setUser($teacher); > $this->assertEquals(1, $DB->count_records('xapi_states')); > $this->expectOutputRegex('/submitted:/'); > // Check nothing happens when given activity id doesn't exist. set_config('fullnamedisplay', 'firstname, lastnamephonetic'); > h5pactivity_delete_instance($activity->id + 1); h5pactivity_print_recent_activity($course, false, time() - 3600); > $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id])); } > $this->assertEquals(2, $DB->count_records('grade_items')); > $this->assertEquals(2, $DB->count_records('grade_grades')); /** > $this->assertEquals(1, $DB->count_records('xapi_states')); * Test that h5pactivity_get_recent_mod_activity fetches the h5pactivity correctly. > * > // Check the H5P instance and its associated data is removed. * @covers ::h5pactivity_get_recent_mod_activity > h5pactivity_delete_instance($activity->id); */ > $this->assertEmpty($DB->get_record('h5pactivity', ['id' => $activity->id])); public function test_h5pactivity_get_recent_mod_activity() { > $this->assertEquals(1, $DB->count_records('grade_items')); $this->resetAfterTest(); > $this->assertEquals(1, $DB->count_records('grade_grades')); $this->setAdminUser(); > $this->assertEquals(0, $DB->count_records('xapi_states')); > } $course = $this->getDataGenerator()->create_course(); > $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); > /**
$student = $this->getDataGenerator()->create_and_enrol($course, 'student'); $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]); $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); $manager = manager::create_from_instance($activity); $cm = $manager->get_coursemodule(); $user = $student; $params = ['cmid' => $cm->id, 'userid' => $user->id]; $generator->create_content($activity, $params); $index = 1; $activities = [ $index => (object) [ 'type' => 'h5pactivity', 'cmid' => $cm->id, ], ]; $this->setUser($teacher); h5pactivity_get_recent_mod_activity($activities, $index, time() - HOURSECS, $course->id, $cm->id); $activity = $activities[1]; $this->assertEquals("h5pactivity", $activity->type); $this->assertEquals($student->id, $activity->user->id); } /** * Test that h5pactivity_get_recent_mod_activity fetches activity correctly. * * @covers ::h5pactivity_fetch_recent_activity */ public function test_h5pactivity_fetch_recent_activity() { global $DB; $this->resetAfterTest(); $this->setAdminUser(); $course = $this->getDataGenerator()->create_course(); // Create users and groups. $students = array(); $groups = array(); $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
< for ($i = 1; $i < 4; $i++) {
> for ($i = 1; $i < 6; $i++) {
$students[$i] = $this->getDataGenerator()->create_and_enrol($course, 'student'); $groups[$i] = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); }
> $groups[$i] = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'participation' => 0));
// Update the course set the groupmode SEPARATEGROUPS and forced. update_course((object)array('id' => $course->id, 'groupmode' => SEPARATEGROUPS, 'groupmodeforce' => true)); // Student 1 is in groups 1 and 3. groups_add_member($groups[1], $students[1]); groups_add_member($groups[3], $students[1]); // Student 2 is in groups 1 and 2. groups_add_member($groups[1], $students[2]); groups_add_member($groups[2], $students[2]); // Student 3 is only in group 3. groups_add_member($groups[3], $students[3]);
> // Student 4 is only in group 5 (non-participation). // Grader is only in group 3. > groups_add_member($groups[6], $students[4]); groups_add_member($groups[3], $teacher); > > // Student 5 is not in any groups. $timestart = time() - 1; >
// Create h5pactivity. $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course->id, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT, 'groupmode' => SEPARATEGROUPS]); $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); $cmcontext = \context_module::instance($activity->cmid); assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $cmcontext, true); $manager = manager::create_from_instance($activity); $cm = $manager->get_coursemodule(); // Create attempts. $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); foreach ($students as $student) { $params = ['cmid' => $cm->id, 'userid' => $student->id]; $generator->create_content($activity, $params); } // Get all attempts. $dbparams = [$timestart, $course->id, 'h5pactivity']; $userfieldsapi = \core_user\fields::for_userpic(); $namefields = $userfieldsapi->get_sql('u', false, '', 'userid', false)->selects;; $sql = "SELECT h5pa.id, h5pa.timemodified, cm.id as cmid, $namefields FROM {h5pactivity_attempts} h5pa JOIN {h5pactivity} h5p ON h5p.id = h5pa.h5pactivityid JOIN {course_modules} cm ON cm.instance = h5p.id JOIN {modules} md ON md.id = cm.module JOIN {user} u ON u.id = h5pa.userid WHERE h5pa.timemodified > ? AND h5p.course = ? AND md.name = ? ORDER BY h5pa.timemodified ASC"; $submissions = $DB->get_records_sql($sql, $dbparams); $this->assertCount(count($students), $submissions); // Fetch activity for student (only his own). $this->setUser($students[1]); $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); $this->assertCount(1, $recentactivity); $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid); // Fetch users group info for grader. $this->setUser($teacher); $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); $this->assertCount(2, $recentactivity); // Grader, Student 1 and 3 are in Group 3. $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid); $this->assertEquals($students[3]->id, $recentactivity[$students[3]->id]->userid); // Grader is in Group 2. groups_remove_member($groups[3], $teacher); groups_add_member($groups[2], $teacher); get_fast_modinfo($course->id, 0, true); $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); $this->assertCount(1, $recentactivity); // Grader, Student 2 are in Group 2. $this->assertEquals($students[2]->id, $recentactivity[$students[2]->id]->userid); // Grader is in Group 1. groups_remove_member($groups[2], $teacher); groups_add_member($groups[1], $teacher); get_fast_modinfo($course->id, 0, true); $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); $this->assertCount(2, $recentactivity); // Grader, Student 1 and 2 are in Group 1. $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid); $this->assertEquals($students[2]->id, $recentactivity[$students[2]->id]->userid);
> } > // Grader is in no group. } > groups_remove_member($groups[1], $teacher); > get_fast_modinfo($course->id, 0, true); > $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); > // Student 4 and Student 5 have submissions, but they are not in a participation group, so they do not show up in recent > // activity for separate groups mode. > $this->assertCount(0, $recentactivity); > } > > /** > * Test that h5pactivity_reset_userdata reset user data. > * > * @covers ::h5pactivity_reset_userdata > */ > public function test_h5pactivity_reset_userdata() { > global $DB; > $this->resetAfterTest(); > $this->setAdminUser(); > > $course = $this->getDataGenerator()->create_course(); > $user = $this->getDataGenerator()->create_and_enrol($course, 'student'); > $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]); > $this->setUser($user); > > /** @var \mod_h5pactivity_generator $generator */ > $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); > > /** @var \core_h5p_generator $h5pgenerator */ > $h5pgenerator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); > > // Add an attempt to the H5P activity. > $attemptinfo = [ > 'userid' => $user->id, > 'h5pactivityid' => $activity->id, > 'attempt' => 1, > 'interactiontype' => 'compound', > 'rawscore' => 2, > 'maxscore' => 2, > 'duration' => 1, > 'completion' => 1, > 'success' => 0, > ]; > $generator->create_attempt($attemptinfo); > > // Add also a xAPI state to the H5P activity. > $filerecord = [ > 'contextid' => \context_module::instance($activity->cmid)->id, > 'component' => 'mod_h5pactivity', > 'filearea' => 'package', > 'itemid' => 0, > 'filepath' => '/', > 'filepath' => '/', > 'filename' => 'dummy.h5p', > 'addxapistate' => true, > ]; > $h5pgenerator->generate_h5p_data(false, $filerecord); > > // Check the H5P activity exists and the attempt has been created with the expected data. > $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id])); > $this->assertEquals(2, $DB->count_records('grade_items')); > $this->assertEquals(2, $DB->count_records('grade_grades')); > $this->assertEquals(1, $DB->count_records('xapi_states')); > > // Check nothing happens when reset_h5pactivity is not set. > $data = new \stdClass(); > h5pactivity_reset_userdata($data); > $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id])); > $this->assertEquals(2, $DB->count_records('grade_items')); > $this->assertEquals(2, $DB->count_records('grade_grades')); > $this->assertEquals(1, $DB->count_records('xapi_states')); > $this->assertEquals(1, $DB->count_records('xapi_states')); > > // Check nothing happens when reset_h5pactivity is not set. > $data = (object) [ > 'courseid' => $course->id, > ]; > h5pactivity_reset_userdata($data); > $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id])); > $this->assertEquals(2, $DB->count_records('grade_items')); > $this->assertEquals(2, $DB->count_records('grade_grades')); > $this->assertEquals(1, $DB->count_records('xapi_states')); > $this->assertEquals(1, $DB->count_records('xapi_states')); > > // Check nothing happens when the given course doesn't exist. > $data = (object) [ > 'reset_h5pactivity' => true, > 'courseid' => $course->id + 1, > ]; > h5pactivity_reset_userdata($data); > $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id])); > $this->assertEquals(2, $DB->count_records('grade_items')); > $this->assertEquals(2, $DB->count_records('grade_grades')); > $this->assertEquals(1, $DB->count_records('xapi_states')); > $this->assertEquals(1, $DB->count_records('xapi_states')); > > // Check the H5P instance and its associated data is reset. > $data = (object) [ > 'reset_h5pactivity' => true, > 'courseid' => $course->id, > ]; > h5pactivity_reset_userdata($data); > $this->assertNotEmpty($DB->get_record('h5pactivity', ['id' => $activity->id])); > $this->assertEquals(2, $DB->count_records('grade_items')); > $this->assertEquals(1, $DB->count_records('grade_grades')); > $this->assertEquals(0, $DB->count_records('xapi_states'));