Current Path : C:/Users/Mahmood/Desktop/moodle8/h5p/tests/ |
Current File : C:/Users/Mahmood/Desktop/moodle8/h5p/tests/framework_test.php |
<?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/>. /** * Testing the H5PFrameworkInterface interface implementation. * * @package core_h5p * @category test * @copyright 2019 Mihail Geshoski <mihail@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; defined('MOODLE_INTERNAL') || die(); /** * * Test class covering the H5PFrameworkInterface interface implementation. * * @package core_h5p * @copyright 2019 Mihail Geshoski <mihail@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @runTestsInSeparateProcesses */ class framework_testcase extends \advanced_testcase { /** @var \core_h5p\framework */ private $framework; /** * Set up function for tests. */ public function setUp() { $factory = new \core_h5p\factory(); $this->framework = $factory->get_framework(); } /** * Test the behaviour of getPlatformInfo(). */ public function test_getPlatformInfo() { global $CFG; $platforminfo = $this->framework->getPlatformInfo(); $expected = array( 'name' => 'Moodle', 'version' => $CFG->version, 'h5pVersion' => $CFG->version ); $this->assertEquals($expected, $platforminfo); } /** * Test the behaviour of fetchExternalData() when the store path is not defined. * * This test is intensive and requires downloading content of an external file, * therefore it might take longer time to execute. * In order to execute this test PHPUNIT_LONGTEST should be set to true in phpunit.xml or directly in config.php. */ public function test_fetchExternalData_no_path_defined() { if (!PHPUNIT_LONGTEST) { $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); } $this->resetAfterTest(); $library = 'H5P.Accordion'; // Provide a valid URL to an external H5P content. $url = $this->getExternalTestFileUrl('/'.$library.'.h5p'); // Test fetching an external H5P content without defining a path to where the file should be stored. $data = $this->framework->fetchExternalData($url, null, true); // The response should not be empty and return true if the file was successfully downloaded. $this->assertNotEmpty($data); $this->assertTrue($data); $h5pfolderpath = $this->framework->getUploadedH5pFolderPath(); // The uploaded file should exist on the filesystem. $this->assertTrue(file_exists($h5pfolderpath . '.h5p')); } /** * Test the behaviour of fetchExternalData() when the store path is defined. * * This test is intensive and requires downloading content of an external file, * therefore it might take longer time to execute. * In order to execute this test PHPUNIT_LONGTEST should be set to true in phpunit.xml or directly in config.php. */ public function test_fetchExternalData_path_defined() { global $CFG; if (!PHPUNIT_LONGTEST) { $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); } $this->resetAfterTest(); $library = 'H5P.Accordion'; // Provide a valid URL to an external H5P content. $url = $this->getExternalTestFileUrl('/'.$library.'.h5p'); $h5pfolderpath = $CFG->tempdir . uniqid('/h5p-'); $data = $this->framework->fetchExternalData($url, null, true, $h5pfolderpath . '.h5p'); // The response should not be empty and return true if the content has been successfully saved to a file. $this->assertNotEmpty($data); $this->assertTrue($data); // The uploaded file should exist on the filesystem. $this->assertTrue(file_exists($h5pfolderpath . '.h5p')); } /** * Test the behaviour of fetchExternalData() when the URL is pointing to an external file that is * not an h5p content. * * This test is intensive and requires downloading content of an external file, * therefore it might take longer time to execute. * In order to execute this test PHPUNIT_LONGTEST should be set to true in phpunit.xml or directly in config.php. */ public function test_fetchExternalData_url_not_h5p() { if (!PHPUNIT_LONGTEST) { // This test is intensive and requires downloading the content of an external file. $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); } $this->resetAfterTest(); // Provide an URL to an external file that is not an H5P content file. $url = $this->getExternalTestFileUrl('/h5pcontenttypes.json'); $data = $this->framework->fetchExternalData($url, null, true); // The response should not be empty and return true if the content has been successfully saved to a file. $this->assertNotEmpty($data); $this->assertTrue($data); // The uploaded file should exist on the filesystem with it's original extension. // NOTE: The file would be later validated by the H5P Validator. $h5pfolderpath = $this->framework->getUploadedH5pFolderPath(); $this->assertTrue(file_exists($h5pfolderpath . '.json')); } /** * Test the behaviour of fetchExternalData() when the URL is invalid. */ public function test_fetchExternalData_url_invalid() { // Provide an invalid URL to an external file. $url = "someprotocol://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"; $data = $this->framework->fetchExternalData($url, null, true); // The response should be empty. $this->assertEmpty($data); } /** * Test the behaviour of setErrorMessage(). */ public function test_setErrorMessage() { // Set an error message and an error code. $message = "Error message"; $code = '404'; // Set an error message. $this->framework->setErrorMessage($message, $code); // Get the error messages. $errormessages = $this->framework->getMessages('error'); $expected = new \stdClass(); $expected->code = 404; $expected->message = 'Error message'; $this->assertEquals($expected, $errormessages[0]); } /** * Test the behaviour of setInfoMessage(). */ public function test_setInfoMessage() { $message = "Info message"; // Set an info message. $this->framework->setInfoMessage($message); // Get the info messages. $infomessages = $this->framework->getMessages('info'); $expected = 'Info message'; $this->assertEquals($expected, $infomessages[0]); } /** * Test the behaviour of getMessages() when requesting the info messages. */ public function test_getMessages_info() { // Set an info message. $this->framework->setInfoMessage("Info message"); // Set an error message. $this->framework->setErrorMessage("Error message 1", 404); // Get the info messages. $infomessages = $this->framework->getMessages('info'); $expected = 'Info message'; // Make sure that only the info message has been returned. $this->assertCount(1, $infomessages); $this->assertEquals($expected, $infomessages[0]); $infomessages = $this->framework->getMessages('info'); // Make sure the info messages have now been removed. $this->assertEmpty($infomessages); } /** * Test the behaviour of getMessages() when requesting the error messages. */ public function test_getMessages_error() { // Set an info message. $this->framework->setInfoMessage("Info message"); // Set an error message. $this->framework->setErrorMessage("Error message 1", 404); // Set another error message. $this->framework->setErrorMessage("Error message 2", 403); // Get the error messages. $errormessages = $this->framework->getMessages('error'); // Make sure that only the error messages are being returned. $this->assertEquals(2, count($errormessages)); $expected1 = (object) [ 'code' => 404, 'message' => 'Error message 1' ]; $expected2 = (object) [ 'code' => 403, 'message' => 'Error message 2' ]; $this->assertEquals($expected1, $errormessages[0]); $this->assertEquals($expected2, $errormessages[1]); $errormessages = $this->framework->getMessages('error'); // Make sure the info messages have now been removed. $this->assertEmpty($errormessages); } /** * Test the behaviour of t() when translating existing string that does not require any arguments. */ public function test_t_existing_string_no_args() { // Existing language string without passed arguments. $translation = $this->framework->t('No copyright information available for this content.'); // Make sure the string translation has been returned. $this->assertEquals('No copyright information available for this content.', $translation); } /** * Test the behaviour of t() when translating existing string that does require parameters. */ public function test_t_existing_string_args() { // Existing language string with passed arguments. $translation = $this->framework->t('Illegal option %option in %library', ['%option' => 'example', '%library' => 'Test library']); // Make sure the string translation has been returned. $this->assertEquals('Illegal option example in Test library', $translation); } /** * Test the behaviour of t() when translating non-existent string. */ public function test_t_non_existent_string() { // Non-existing language string. $message = 'Random message %option'; $translation = $this->framework->t($message); // Make sure a debugging message is triggered. $this->assertDebuggingCalled("String translation cannot be found. Please add a string definition for '" . $message . "' in the core_h5p component."); // As the string does not exist in the mapping array, make sure the passed message is returned. $this->assertEquals($message, $translation); } /** * Test the behaviour of getLibraryFileUrl() when requesting a file URL from an existing library and * the folder name is parsable. **/ public function test_getLibraryFileUrl() { global $CFG; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library record. $lib = $generator->create_library_record('Library', 'Lib', 1, 1); $expected = "{$CFG->wwwroot}/pluginfile.php/1/core_h5p/libraries/{$lib->id}/Library-1.1/library.json"; // Get the URL of a file from an existing library. The provided folder name is parsable. $actual = $this->framework->getLibraryFileUrl('Library-1.1', 'library.json'); // Make sure the expected URL is returned. $this->assertEquals($expected, $actual); } /** * Test the behaviour of getLibraryFileUrl() when requesting a file URL from a non-existent library and * the folder name is parsable. **/ public function test_getLibraryFileUrl_non_existent_library() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library record. $generator->create_library_record('Library', 'Lib', 1, 1); // Get the URL of a file from a non-existent library. The provided folder name is parsable. $actual = $this->framework->getLibraryFileUrl('Library2-1.1', 'library.json'); // Make sure a debugging message is triggered. $this->assertDebuggingCalled('The library "Library2-1.1" does not exist.'); // Make sure that an URL is not returned. $this->assertEquals(null, $actual); } /** * Test the behaviour of getLibraryFileUrl() when requesting a file URL from an existing library and * the folder name is not parsable. **/ public function test_getLibraryFileUrl_not_parsable_folder_name() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library record. $generator->create_library_record('Library', 'Lib', 1, 1); // Get the URL of a file from an existing library. The provided folder name is not parsable. $actual = $this->framework->getLibraryFileUrl('Library1.1', 'library.json'); // Make sure a debugging message is triggered. $this->assertDebuggingCalled( 'The provided string value "Library1.1" is not a valid name for a library folder.'); // Make sure that an URL is not returned. $this->assertEquals(null, $actual); } /** * Test the behaviour of getLibraryFileUrl() when requesting a file URL from a library that has multiple * versions and the folder name is parsable. **/ public function test_getLibraryFileUrl_library_has_multiple_versions() { global $CFG; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create library records with a different minor version. $lib1 = $generator->create_library_record('Library', 'Lib', 1, 1); $lib2 = $generator->create_library_record('Library', 'Lib', 1, 3); $expected = "{$CFG->wwwroot}/pluginfile.php/1/core_h5p/libraries/{$lib2->id}/Library-1.3/library.json"; // Get the URL of a file from an existing library (Library 1.3). The provided folder name is parsable. $actual = $this->framework->getLibraryFileUrl('Library-1.3', 'library.json'); // Make sure the proper URL (from the requested library version) is returned. $this->assertEquals($expected, $actual); } /** * Test the behaviour of getLibraryFileUrl() when requesting a file URL from a library that has multiple * patch versions and the folder name is parsable. **/ public function test_getLibraryFileUrl_library_has_multiple_patch_versions() { global $CFG; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create library records with a different patch version. $lib1 = $generator->create_library_record('Library', 'Lib', 1, 1, 2); $lib2 = $generator->create_library_record('Library', 'Lib', 1, 1, 4); $lib3 = $generator->create_library_record('Library', 'Lib', 1, 1, 3); $expected = "{$CFG->wwwroot}/pluginfile.php/1/core_h5p/libraries/{$lib2->id}/Library-1.1/library.json"; // Get the URL of a file from an existing library. The provided folder name is parsable. $actual = $this->framework->getLibraryFileUrl('Library-1.1', 'library.json'); // Make sure the proper URL (from the latest library patch) is returned. $this->assertEquals($expected, $actual); } /** * Test the behaviour of getLibraryFileUrl() when requesting a file URL from a sub-folder * of an existing library and the folder name is parsable. **/ public function test_getLibraryFileUrl_library_subfolder() { global $CFG; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library record. $lib = $generator->create_library_record('Library', 'Lib', 1, 1); $expected = "{$CFG->wwwroot}/pluginfile.php/1/core_h5p/libraries/{$lib->id}/Library-1.1/css/example.css"; // Get the URL of a file from a sub-folder from an existing library. The provided folder name is parsable. $actual = $this->framework->getLibraryFileUrl('Library-1.1/css', 'example.css'); // Make sure the proper URL is returned. $this->assertEquals($expected, $actual); } /** * Test the behaviour of loadAddons(). */ public function test_loadAddons() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a Library addon (1.1). $generator->create_library_record('Library', 'Lib', 1, 1, 2, '', '/regex1/'); // Create a Library addon (1.3). $generator->create_library_record('Library', 'Lib', 1, 3, 2, '', '/regex2/'); // Create a Library addon (1.2). $generator->create_library_record('Library', 'Lib', 1, 2, 2, '', '/regex3/'); // Create a Library1 addon (1.2) $generator->create_library_record('Library1', 'Lib1', 1, 2, 2, '', '/regex11/'); // Load the latest version of each addon. $addons = $this->framework->loadAddons(); // The addons array should return 2 results (Library and Library1 addon). $this->assertCount(2, $addons); // Make sure the version 1.3 is the latest 'Library' addon version. $this->assertEquals('Library', $addons[0]['machineName']); $this->assertEquals(1, $addons[0]['majorVersion']); $this->assertEquals(3, $addons[0]['minorVersion']); // Make sure the version 1.2 is the latest 'Library1' addon version. $this->assertEquals('Library1', $addons[1]['machineName']); $this->assertEquals(1, $addons[1]['majorVersion']); $this->assertEquals(2, $addons[1]['minorVersion']); } /** * Test the behaviour of loadLibraries(). */ public function test_loadLibraries() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $generator->generate_h5p_data(); // Load all libraries. $libraries = $this->framework->loadLibraries(); // Make sure all libraries are returned. $this->assertNotEmpty($libraries); $this->assertCount(6, $libraries); $this->assertEquals('MainLibrary', $libraries['MainLibrary'][0]->machine_name); $this->assertEquals('1', $libraries['MainLibrary'][0]->major_version); $this->assertEquals('0', $libraries['MainLibrary'][0]->minor_version); $this->assertEquals('1', $libraries['MainLibrary'][0]->patch_version); $this->assertEquals('MainLibrary', $libraries['MainLibrary'][0]->machine_name); } /** * Test the behaviour of test_getLibraryId() when requesting an existing machine name. */ public function test_getLibraryId_existing_machine_name() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library. $lib = $generator->create_library_record('Library', 'Lib', 1, 1, 2); // Request the library ID of the library with machine name 'Library'. $libraryid = $this->framework->getLibraryId('Library'); // Make sure the library ID is being returned. $this->assertNotFalse($libraryid); $this->assertEquals($lib->id, $libraryid); } /** * Test the behaviour of test_getLibraryId() when requesting a non-existent machine name. */ public function test_getLibraryId_non_existent_machine_name() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library. $generator->create_library_record('Library', 'Lib', 1, 1, 2); // Request the library ID of the library with machinename => 'TestLibrary' (non-existent). $libraryid = $this->framework->getLibraryId('TestLibrary'); // Make sure the library ID not being returned. $this->assertFalse($libraryid); } /** * Test the behaviour of test_getLibraryId() when requesting a non-existent major version. */ public function test_getLibraryId_non_existent_major_version() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library. $generator->create_library_record('Library', 'Lib', 1, 1, 2); // Request the library ID of the library with machine name => 'Library', majorversion => 2 (non-existent). $libraryid = $this->framework->getLibraryId('Library', 2); // Make sure the library ID not being returned. $this->assertFalse($libraryid); } /** * Test the behaviour of test_getLibraryId() when requesting a non-existent minor version. */ public function test_getLibraryId_non_existent_minor_version() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library. $generator->create_library_record('Library', 'Lib', 1, 1, 2); // Request the library ID of the library with machine name => 'Library', // majorversion => 1, minorversion => 2 (non-existent). $libraryid = $this->framework->getLibraryId('Library', 1, 2); // Make sure the library ID not being returned. $this->assertFalse($libraryid); } /** * Test the behaviour of isPatchedLibrary(). * * @dataProvider test_isPatchedLibrary_provider * @param array $libraryrecords Array containing data for the library creation * @param array $testlibrary Array containing the test library data * @param bool $expected The expectation whether the library is patched or not **/ public function test_isPatchedLibrary(array $libraryrecords, array $testlibrary, bool $expected): void { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); foreach ($libraryrecords as $library) { call_user_func_array([$generator, 'create_library_record'], $library); } $this->assertEquals($expected, $this->framework->isPatchedLibrary($testlibrary)); } /** * Data provider for test_isPatchedLibrary(). * * @return array */ public function test_isPatchedLibrary_provider(): array { return [ 'Unpatched library. No different versioning' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 1, 'minorVersion' => 1, 'patchVersion' => 2 ], false, ], 'Major version identical; Minor version identical; Patch version newer' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 1, 'minorVersion' => 1, 'patchVersion' => 3 ], true, ], 'Major version identical; Minor version newer; Patch version newer' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 1, 'minorVersion' => 2, 'patchVersion' => 3 ], false, ], 'Major version identical; Minor version identical; Patch version older' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 1, 'minorVersion' => 1, 'patchVersion' => 1 ], false, ], 'Major version identical; Minor version newer; Patch version older' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 1, 'minorVersion' => 2, 'patchVersion' => 1 ], false, ], 'Major version newer; Minor version identical; Patch version older' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 2, 'minorVersion' => 1, 'patchVersion' => 1 ], false, ], 'Major version newer; Minor version identical; Patch version newer' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 2, 'minorVersion' => 1, 'patchVersion' => 3 ], false, ], 'Major version older; Minor version identical; Patch version older' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 0, 'minorVersion' => 1, 'patchVersion' => 1 ], false, ], 'Major version older; Minor version identical; Patch version newer' => [ [ ['TestLibrary', 'Test', 1, 1, 2], ], [ 'machineName' => 'TestLibrary', 'majorVersion' => 0, 'minorVersion' => 1, 'patchVersion' => 3 ], false, ], ]; } /** * Test the behaviour of isInDevMode(). */ public function test_isInDevMode() { $isdevmode = $this->framework->isInDevMode(); $this->assertFalse($isdevmode); } /** * Test the behaviour of mayUpdateLibraries(). */ public function test_mayUpdateLibraries(): void { global $DB; $this->resetAfterTest(); // Create some users. $contextsys = \context_system::instance(); $user = $this->getDataGenerator()->create_user(); $admin = get_admin(); $managerrole = $DB->get_record('role', ['shortname' => 'manager'], '*', MUST_EXIST); $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST); $manager = $this->getDataGenerator()->create_user(); role_assign($managerrole->id, $manager->id, $contextsys); // Create a course with a label and enrol the user. $course = $this->getDataGenerator()->create_course(); $label = $this->getDataGenerator()->create_module('label', ['course' => $course->id]); list(, $labelcm) = get_course_and_cm_from_instance($label->id, 'label'); $contextlabel = \context_module::instance($labelcm->id); $this->getDataGenerator()->enrol_user($user->id, $course->id, 'student'); // Create the .h5p file. $path = __DIR__ . '/fixtures/h5ptest.zip'; // Admin and manager should have permission to update libraries. $file = helper::create_fake_stored_file_from_path($path, $admin->id, $contextsys); $this->framework->set_file($file); $mayupdatelib = $this->framework->mayUpdateLibraries(); $this->assertTrue($mayupdatelib); $file = helper::create_fake_stored_file_from_path($path, $manager->id, $contextsys); $this->framework->set_file($file); $mayupdatelib = $this->framework->mayUpdateLibraries(); $this->assertTrue($mayupdatelib); // By default, normal user hasn't permission to update libraries (in both contexts, system and module label). $file = helper::create_fake_stored_file_from_path($path, $user->id, $contextsys); $this->framework->set_file($file); $mayupdatelib = $this->framework->mayUpdateLibraries(); $this->assertFalse($mayupdatelib); $file = helper::create_fake_stored_file_from_path($path, $user->id, $contextlabel); $this->framework->set_file($file); $mayupdatelib = $this->framework->mayUpdateLibraries(); $this->assertFalse($mayupdatelib); // If the current user (admin) can update libraries, the method should return true (even if the file userid hasn't the // required capabilility in the file context). $file = helper::create_fake_stored_file_from_path($path, $admin->id, $contextlabel); $this->framework->set_file($file); $mayupdatelib = $this->framework->mayUpdateLibraries(); $this->assertTrue($mayupdatelib); // If the update capability is assigned to the user, they should be able to update the libraries (only in the context // where the capability has been assigned). $file = helper::create_fake_stored_file_from_path($path, $user->id, $contextlabel); $this->framework->set_file($file); $mayupdatelib = $this->framework->mayUpdateLibraries(); $this->assertFalse($mayupdatelib); assign_capability('moodle/h5p:updatelibraries', CAP_ALLOW, $studentrole->id, $contextlabel); $mayupdatelib = $this->framework->mayUpdateLibraries(); $this->assertTrue($mayupdatelib); $file = helper::create_fake_stored_file_from_path($path, $user->id, $contextsys); $this->framework->set_file($file); $mayupdatelib = $this->framework->mayUpdateLibraries(); $this->assertFalse($mayupdatelib); } /** * Test the behaviour of get_file() and set_file(). */ public function test_get_file(): void { $this->resetAfterTest(); // Create some users. $contextsys = \context_system::instance(); $user = $this->getDataGenerator()->create_user(); // The H5P file. $path = __DIR__ . '/fixtures/h5ptest.zip'; // An error should be raised when it's called before initialitzing it. $this->expectException('coding_exception'); $this->expectExceptionMessage('Using get_file() before file is set'); $this->framework->get_file(); // Check the value when only path and user are set. $file = helper::create_fake_stored_file_from_path($path, $user->id); $this->framework->set_file($file); $file = $this->framework->get_file(); $this->assertEquals($user->id, $$file->get_userid()); $this->assertEquals($contextsys->id, $file->get_contextid()); // Check the value when also the context is set. $course = $this->getDataGenerator()->create_course(); $contextcourse = \context_course::instance($course->id); $file = helper::create_fake_stored_file_from_path($path, $user->id, $contextcourse); $this->framework->set_file($file); $file = $this->framework->get_file(); $this->assertEquals($user->id, $$file->get_userid()); $this->assertEquals($contextcourse->id, $file->get_contextid()); } /** * Test the behaviour of saveLibraryData() when saving data for a new library. */ public function test_saveLibraryData_new_library() { global $DB; $this->resetAfterTest(); $librarydata = array( 'title' => 'Test', 'machineName' => 'TestLibrary', 'majorVersion' => '1', 'minorVersion' => '0', 'patchVersion' => '2', 'runnable' => 1, 'fullscreen' => 1, 'preloadedJs' => array( array( 'path' => 'js/name.min.js' ) ), 'preloadedCss' => array( array( 'path' => 'css/name.css' ) ), 'dropLibraryCss' => array( array( 'machineName' => 'Name2' ) ) ); // Create a new library. $this->framework->saveLibraryData($librarydata); $library = $DB->get_record('h5p_libraries', ['machinename' => $librarydata['machineName']]); // Make sure the library data was properly saved. $this->assertNotEmpty($library); $this->assertNotEmpty($librarydata['libraryId']); $this->assertEquals($librarydata['title'], $library->title); $this->assertEquals($librarydata['machineName'], $library->machinename); $this->assertEquals($librarydata['majorVersion'], $library->majorversion); $this->assertEquals($librarydata['minorVersion'], $library->minorversion); $this->assertEquals($librarydata['patchVersion'], $library->patchversion); $this->assertEquals($librarydata['preloadedJs'][0]['path'], $library->preloadedjs); $this->assertEquals($librarydata['preloadedCss'][0]['path'], $library->preloadedcss); $this->assertEquals($librarydata['dropLibraryCss'][0]['machineName'], $library->droplibrarycss); } /** * Test the behaviour of saveLibraryData() when saving (updating) data for an existing library. */ public function test_saveLibraryData_existing_library() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library record. $library = $generator->create_library_record('TestLibrary', 'Test', 1, 0, 2); $librarydata = array( 'libraryId' => $library->id, 'title' => 'Test1', 'machineName' => 'TestLibrary', 'majorVersion' => '1', 'minorVersion' => '2', 'patchVersion' => '2', 'runnable' => 1, 'fullscreen' => 1, 'preloadedJs' => array( array( 'path' => 'js/name.min.js' ) ), 'preloadedCss' => array( array( 'path' => 'css/name.css' ) ), 'dropLibraryCss' => array( array( 'machineName' => 'Name2' ) ) ); // Update the library. $this->framework->saveLibraryData($librarydata, false); $library = $DB->get_record('h5p_libraries', ['machinename' => $librarydata['machineName']]); // Make sure the library data was properly updated. $this->assertNotEmpty($library); $this->assertNotEmpty($librarydata['libraryId']); $this->assertEquals($librarydata['title'], $library->title); $this->assertEquals($librarydata['machineName'], $library->machinename); $this->assertEquals($librarydata['majorVersion'], $library->majorversion); $this->assertEquals($librarydata['minorVersion'], $library->minorversion); $this->assertEquals($librarydata['patchVersion'], $library->patchversion); $this->assertEquals($librarydata['preloadedJs'][0]['path'], $library->preloadedjs); $this->assertEquals($librarydata['preloadedCss'][0]['path'], $library->preloadedcss); $this->assertEquals($librarydata['dropLibraryCss'][0]['machineName'], $library->droplibrarycss); } /** * Test the behaviour of insertContent(). */ public function test_insertContent() { global $DB; $this->resetAfterTest(); $content = array( 'params' => json_encode(['param1' => 'Test']), 'library' => array( 'libraryId' => 1 ), 'disable' => 8 ); // Insert h5p content. $contentid = $this->framework->insertContent($content); // Get the entered content from the db. $dbcontent = $DB->get_record('h5p', ['id' => $contentid]); // Make sure the h5p content was properly inserted. $this->assertNotEmpty($dbcontent); $this->assertEquals($content['params'], $dbcontent->jsoncontent); $this->assertEquals($content['library']['libraryId'], $dbcontent->mainlibraryid); $this->assertEquals($content['disable'], $dbcontent->displayoptions); } /** * Test the behaviour of insertContent(). */ public function test_insertContent_latestlibrary() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library record. $lib = $generator->create_library_record('TestLibrary', 'Test', 1, 1, 2); $content = array( 'params' => json_encode(['param1' => 'Test']), 'library' => array( 'libraryId' => 0, 'machineName' => 'TestLibrary', ), 'disable' => 8 ); // Insert h5p content. $contentid = $this->framework->insertContent($content); // Get the entered content from the db. $dbcontent = $DB->get_record('h5p', ['id' => $contentid]); // Make sure the h5p content was properly inserted. $this->assertNotEmpty($dbcontent); $this->assertEquals($content['params'], $dbcontent->jsoncontent); $this->assertEquals($content['disable'], $dbcontent->displayoptions); // As the libraryId was empty, the latest library has been used. $this->assertEquals($lib->id, $dbcontent->mainlibraryid); } /** * Test the behaviour of updateContent(). */ public function test_updateContent() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library record. $lib = $generator->create_library_record('TestLibrary', 'Test', 1, 1, 2); // Create an h5p content with 'TestLibrary' as it's main library. $contentid = $generator->create_h5p_record($lib->id); $content = array( 'id' => $contentid, 'params' => json_encode(['param2' => 'Test2']), 'library' => array( 'libraryId' => $lib->id ), 'disable' => 8 ); // Update the h5p content. $this->framework->updateContent($content); $h5pcontent = $DB->get_record('h5p', ['id' => $contentid]); // Make sure the h5p content was properly updated. $this->assertNotEmpty($h5pcontent); $this->assertEquals($content['params'], $h5pcontent->jsoncontent); $this->assertEquals($content['library']['libraryId'], $h5pcontent->mainlibraryid); $this->assertEquals($content['disable'], $h5pcontent->displayoptions); } /** * Test the behaviour of saveLibraryDependencies(). */ public function test_saveLibraryDependencies() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library 'Library'. $library = $generator->create_library_record('Library', 'Title'); // Create a library 'DependencyLibrary1'. $dependency1 = $generator->create_library_record('DependencyLibrary1', 'DependencyTitle1'); // Create a library 'DependencyLibrary2'. $dependency2 = $generator->create_library_record('DependencyLibrary2', 'DependencyTitle2'); $dependencies = array( array( 'machineName' => $dependency1->machinename, 'majorVersion' => $dependency1->majorversion, 'minorVersion' => $dependency1->minorversion ), array( 'machineName' => $dependency2->machinename, 'majorVersion' => $dependency2->majorversion, 'minorVersion' => $dependency2->minorversion ), ); // Set 'DependencyLibrary1' and 'DependencyLibrary2' as library dependencies of 'Library'. $this->framework->saveLibraryDependencies($library->id, $dependencies, 'preloaded'); $libdependencies = $DB->get_records('h5p_library_dependencies', ['libraryid' => $library->id], 'id ASC'); // Make sure the library dependencies for 'Library' are properly set. $this->assertEquals(2, count($libdependencies)); $this->assertEquals($dependency1->id, reset($libdependencies)->requiredlibraryid); $this->assertEquals($dependency2->id, end($libdependencies)->requiredlibraryid); } /** * Test the behaviour of deleteContentData(). */ public function test_deleteContentData() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate some h5p related data. $data = $generator->generate_h5p_data(); $h5pid = $data->h5pcontent->h5pid; $h5pcontent = $DB->get_record('h5p', ['id' => $h5pid]); // Make sure the particular h5p content exists in the DB. $this->assertNotEmpty($h5pcontent); // Get the h5p content libraries from the DB. $h5pcontentlibraries = $DB->get_records('h5p_contents_libraries', ['h5pid' => $h5pid]); // Make sure the content libraries exists in the DB. $this->assertNotEmpty($h5pcontentlibraries); $this->assertCount(5, $h5pcontentlibraries); // Delete the h5p content and it's related data. $this->framework->deleteContentData($h5pid); $h5pcontent = $DB->get_record('h5p', ['id' => $h5pid]); $h5pcontentlibraries = $DB->get_record('h5p_contents_libraries', ['h5pid' => $h5pid]); // The particular h5p content should no longer exist in the db. $this->assertEmpty($h5pcontent); // The particular content libraries should no longer exist in the db. $this->assertEmpty($h5pcontentlibraries); } /** * Test the behaviour of deleteLibraryUsage(). */ public function test_deleteLibraryUsage() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate some h5p related data. $data = $generator->generate_h5p_data(); $h5pid = $data->h5pcontent->h5pid; // Get the h5p content libraries from the DB. $h5pcontentlibraries = $DB->get_records('h5p_contents_libraries', ['h5pid' => $h5pid]); // The particular h5p content should have 5 content libraries. $this->assertNotEmpty($h5pcontentlibraries); $this->assertCount(5, $h5pcontentlibraries); // Delete the h5p content and it's related data. $this->framework->deleteLibraryUsage($h5pid); // Get the h5p content libraries from the DB. $h5pcontentlibraries = $DB->get_record('h5p_contents_libraries', ['h5pid' => $h5pid]); // The particular h5p content libraries should no longer exist in the db. $this->assertEmpty($h5pcontentlibraries); } /** * Test the behaviour of test_saveLibraryUsage(). */ public function test_saveLibraryUsage() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library 'Library'. $library = $generator->create_library_record('Library', 'Title'); // Create a library 'DependencyLibrary1'. $dependency1 = $generator->create_library_record('DependencyLibrary1', 'DependencyTitle1'); // Create a library 'DependencyLibrary2'. $dependency2 = $generator->create_library_record('DependencyLibrary2', 'DependencyTitle2'); // Create an h5p content with 'Library' as it's main library. $contentid = $generator->create_h5p_record($library->id); $dependencies = array( array( 'library' => array( 'libraryId' => $dependency1->id, 'machineName' => $dependency1->machinename, 'dropLibraryCss' => $dependency1->droplibrarycss ), 'type' => 'preloaded', 'weight' => 1 ), array( 'library' => array( 'libraryId' => $dependency2->id, 'machineName' => $dependency2->machinename, 'dropLibraryCss' => $dependency2->droplibrarycss ), 'type' => 'preloaded', 'weight' => 2 ), ); // Save 'DependencyLibrary1' and 'DependencyLibrary2' as h5p content libraries. $this->framework->saveLibraryUsage($contentid, $dependencies); // Get the h5p content libraries from the DB. $libdependencies = $DB->get_records('h5p_contents_libraries', ['h5pid' => $contentid], 'id ASC'); // Make sure that 'DependencyLibrary1' and 'DependencyLibrary2' are properly set as h5p content libraries. $this->assertEquals(2, count($libdependencies)); $this->assertEquals($dependency1->id, reset($libdependencies)->libraryid); $this->assertEquals($dependency2->id, end($libdependencies)->libraryid); } /** * Test the behaviour of getLibraryUsage() without skipping a particular h5p content. */ public function test_getLibraryUsage_no_skip_content() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $generateddata = $generator->generate_h5p_data(); // The Id of the library 'Library1'. $library1id = $generateddata->lib1->data->id; // The Id of the library 'Library2'. $library2id = $generateddata->lib2->data->id; // The Id of the library 'Library5'. $library5id = $generateddata->lib5->data->id; // Get the library usage for 'Library1' (do not skip content). $data = $this->framework->getLibraryUsage($library1id); $expected = array( 'content' => 1, 'libraries' => 1 ); // Make sure 'Library1' is used by 1 content and is a dependency to 1 library. $this->assertEquals($expected, $data); // Get the library usage for 'Library2' (do not skip content). $data = $this->framework->getLibraryUsage($library2id); $expected = array( 'content' => 1, 'libraries' => 2, ); // Make sure 'Library2' is used by 1 content and is a dependency to 2 libraries. $this->assertEquals($expected, $data); // Get the library usage for 'Library5' (do not skip content). $data = $this->framework->getLibraryUsage($library5id); $expected = array( 'content' => 0, 'libraries' => 1, ); // Make sure 'Library5' is not used by any content and is a dependency to 1 library. $this->assertEquals($expected, $data); } /** * Test the behaviour of getLibraryUsage() when skipping a particular content. */ public function test_getLibraryUsage_skip_content() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $generateddata = $generator->generate_h5p_data(); // The Id of the library 'Library1'. $library1id = $generateddata->lib1->data->id; // Get the library usage for 'Library1' (skip content). $data = $this->framework->getLibraryUsage($library1id, true); $expected = array( 'content' => -1, 'libraries' => 1, ); // Make sure 'Library1' is a dependency to 1 library. $this->assertEquals($expected, $data); } /** * Test the behaviour of loadLibrary() when requesting an existing library. */ public function test_loadLibrary_existing_library() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $generateddata = $generator->generate_h5p_data(); // The library data of 'Library1'. $library1 = $generateddata->lib1->data; // The library data of 'Library5'. $library5 = $generateddata->lib5->data; // The preloaded dependencies. $preloadeddependencies = array(); foreach ($generateddata->lib1->dependencies as $preloadeddependency) { $preloadeddependencies[] = array( 'machineName' => $preloadeddependency->machinename, 'majorVersion' => $preloadeddependency->majorversion, 'minorVersion' => $preloadeddependency->minorversion ); } // Create a dynamic dependency. $generator->create_library_dependency_record($library1->id, $library5->id, 'dynamic'); $dynamicdependencies[] = array( 'machineName' => $library5->machinename, 'majorVersion' => $library5->majorversion, 'minorVersion' => $library5->minorversion ); // Load 'Library1' data. $data = $this->framework->loadLibrary($library1->machinename, $library1->majorversion, $library1->minorversion); $expected = array( 'libraryId' => $library1->id, 'title' => $library1->title, 'machineName' => $library1->machinename, 'majorVersion' => $library1->majorversion, 'minorVersion' => $library1->minorversion, 'patchVersion' => $library1->patchversion, 'runnable' => $library1->runnable, 'fullscreen' => $library1->fullscreen, 'embedTypes' => $library1->embedtypes, 'preloadedJs' => $library1->preloadedjs, 'preloadedCss' => $library1->preloadedcss, 'dropLibraryCss' => $library1->droplibrarycss, 'semantics' => $library1->semantics, 'preloadedDependencies' => $preloadeddependencies, 'dynamicDependencies' => $dynamicdependencies ); // Make sure the 'Library1' data is properly loaded. $this->assertEquals($expected, $data); } /** * Test the behaviour of loadLibrary() when requesting a non-existent library. */ public function test_loadLibrary_non_existent_library() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $generator->generate_h5p_data(); // Attempt to load a non-existent library. $data = $this->framework->loadLibrary('MissingLibrary', 1, 2); // Make sure nothing is loaded. $this->assertFalse($data); } /** * Test the behaviour of loadLibrarySemantics(). * * @dataProvider test_loadLibrarySemantics_provider * @param array $libraryrecords Array containing data for the library creation * @param array $testlibrary Array containing the test library data * @param string $expected The expected semantics value **/ public function test_loadLibrarySemantics(array $libraryrecords, array $testlibrary, string $expected): void { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); foreach ($libraryrecords as $library) { call_user_func_array([$generator, 'create_library_record'], $library); } $this->assertEquals($expected, $this->framework->loadLibrarySemantics( $testlibrary['machinename'], $testlibrary['majorversion'], $testlibrary['minorversion'])); } /** * Data provider for test_loadLibrarySemantics(). * * @return array */ public function test_loadLibrarySemantics_provider(): array { $semantics = json_encode( [ 'type' => 'text', 'name' => 'text', 'label' => 'Plain text', 'description' => 'Please add some text' ] ); return [ 'Library with semantics' => [ [ ['Library1', 'Lib1', 1, 1, 2, $semantics], ], [ 'machinename' => 'Library1', 'majorversion' => 1, 'minorversion' => 1 ], $semantics, ], 'Library without semantics' => [ [ ['Library2', 'Lib2', 1, 2, 2, ''], ], [ 'machinename' => 'Library2', 'majorversion' => 1, 'minorversion' => 2 ], '', ] ]; } /** * Test the behaviour of alterLibrarySemantics(). */ public function test_alterLibrarySemantics() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $semantics = json_encode( array( 'type' => 'text', 'name' => 'text', 'label' => 'Plain text', 'description' => 'Please add some text' ) ); // Create a library 'Library1' with semantics. $library1 = $generator->create_library_record('Library1', 'Lib1', 1, 1, 2, $semantics); $updatedsemantics = array( 'type' => 'text', 'name' => 'updated text', 'label' => 'Updated text', 'description' => 'Please add some text' ); // Alter the semantics of 'Library1'. $this->framework->alterLibrarySemantics($updatedsemantics, 'Library1', 1, 1); // Get the semantics of 'Library1' from the DB. $currentsemantics = $DB->get_field('h5p_libraries', 'semantics', array('id' => $library1->id)); // The semantics for Library1 should be successfully updated. $this->assertEquals(json_encode($updatedsemantics), $currentsemantics); } /** * Test the behaviour of deleteLibraryDependencies() when requesting to delete the * dependencies of an existing library. */ public function test_deleteLibraryDependencies_existing_library() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(); // The data of the library 'Library1'. $library1 = $data->lib1->data; // Get the dependencies of 'Library1'. $dependencies = $DB->get_records('h5p_library_dependencies', ['libraryid' => $library1->id]); // The 'Library1' should have 3 dependencies ('Library2', 'Library3', 'Library4'). $this->assertCount(3, $dependencies); // Delete the dependencies of 'Library1'. $this->framework->deleteLibraryDependencies($library1->id); $dependencies = $DB->get_records('h5p_library_dependencies', ['libraryid' => $library1->id]); // The 'Library1' should have 0 dependencies. $this->assertCount(0, $dependencies); } /** * Test the behaviour of deleteLibraryDependencies() when requesting to delete the * dependencies of a non-existent library. */ public function test_deleteLibraryDependencies_non_existent_library() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(); // The data of the library 'Library1'. $library1 = $data->lib1->data; // Get the dependencies of 'Library1'. $dependencies = $DB->get_records('h5p_library_dependencies', ['libraryid' => $library1->id]); // The 'Library1' should have 3 dependencies ('Library2', 'Library3', 'Library4'). $this->assertCount(3, $dependencies); // Delete the dependencies of a non-existent library. $this->framework->deleteLibraryDependencies(0); $dependencies = $DB->get_records('h5p_library_dependencies', ['libraryid' => $library1->id]); // The 'Library1' should have 3 dependencies. $this->assertCount(3, $dependencies); } /** * Test the behaviour of deleteLibrary(). */ public function test_deleteLibrary() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(true); // The data of the 'Library1' library. $library1 = $data->lib1->data; // Get the library dependencies of 'Library1'. $dependencies = $DB->get_records('h5p_library_dependencies', ['libraryid' => $library1->id]); // The 'Library1' should have 3 library dependencies ('Library2', 'Library3', 'Library4'). $this->assertCount(3, $dependencies); // Return the created 'Library1' files. $libraryfiles = $DB->get_records('files', array( 'component' => \core_h5p\file_storage::COMPONENT, 'filearea' => \core_h5p\file_storage::LIBRARY_FILEAREA, 'itemid' => $library1->id ) ); // The library ('Library1') should have 7 related folders/files. $this->assertCount(7, $libraryfiles); // Delete the library. $this->framework->deleteLibrary($library1); $lib1 = $DB->get_record('h5p_libraries', ['machinename' => $library1->machinename]); $dependencies = $DB->get_records('h5p_library_dependencies', ['libraryid' => $library1->id]); $libraryfiles = $DB->get_records('files', array( 'component' => \core_h5p\file_storage::COMPONENT, 'filearea' => \core_h5p\file_storage::LIBRARY_FILEAREA, 'itemid' => $library1->id ) ); // The 'Library1' should not exist. $this->assertEmpty($lib1); // The library ('Library1') should have 0 dependencies. $this->assertCount(0, $dependencies); // The library (library1) should have 0 related folders/files. $this->assertCount(0, $libraryfiles); } /** * Test the behaviour of loadContent(). */ public function test_loadContent() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(); // The Id of the created h5p content. $h5pid = $data->h5pcontent->h5pid; // Get the h5p content data from the DB. $h5p = $DB->get_record('h5p', ['id' => $h5pid]); // The data of content's main library ('MainLibrary'). $mainlibrary = $data->mainlib->data; // Load the h5p content. $content = $this->framework->loadContent($h5pid); $expected = array( 'id' => $h5p->id, 'params' => $h5p->jsoncontent, 'embedType' => 'iframe', 'disable' => $h5p->displayoptions, 'title' => $mainlibrary->title, 'slug' => \H5PCore::slugify($mainlibrary->title) . '-' . $h5p->id, 'filtered' => $h5p->filtered, 'libraryId' => $mainlibrary->id, 'libraryName' => $mainlibrary->machinename, 'libraryMajorVersion' => $mainlibrary->majorversion, 'libraryMinorVersion' => $mainlibrary->minorversion, 'libraryEmbedTypes' => $mainlibrary->embedtypes, 'libraryFullscreen' => $mainlibrary->fullscreen, 'metadata' => '' ); // The returned content should match the expected array. $this->assertEquals($expected, $content); } /** * Test the behaviour of loadContentDependencies() when requesting content dependencies * without specifying the dependency type. */ public function test_loadContentDependencies_no_type_defined() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(); // The Id of the h5p content. $h5pid = $data->h5pcontent->h5pid; // The content dependencies. $dependencies = $data->h5pcontent->contentdependencies; // Add Library5 as a content dependency (dynamic dependency type). $library5 = $data->lib5->data; $generator->create_contents_libraries_record($h5pid, $library5->id, 'dynamic'); // Get all content dependencies. $contentdependencies = $this->framework->loadContentDependencies($h5pid); $expected = array(); foreach ($dependencies as $dependency) { $expected[$dependency->machinename] = array( 'libraryId' => $dependency->id, 'machineName' => $dependency->machinename, 'majorVersion' => $dependency->majorversion, 'minorVersion' => $dependency->minorversion, 'patchVersion' => $dependency->patchversion, 'preloadedCss' => $dependency->preloadedcss, 'preloadedJs' => $dependency->preloadedjs, 'dropCss' => '0', 'dependencyType' => 'preloaded' ); } $expected = array_merge($expected, array( 'Library5' => array( 'libraryId' => $library5->id, 'machineName' => $library5->machinename, 'majorVersion' => $library5->majorversion, 'minorVersion' => $library5->minorversion, 'patchVersion' => $library5->patchversion, 'preloadedCss' => $library5->preloadedcss, 'preloadedJs' => $library5->preloadedjs, 'dropCss' => '0', 'dependencyType' => 'dynamic' ) ) ); // The loaded content dependencies should return 6 libraries. $this->assertCount(6, $contentdependencies); $this->assertEquals($expected, $contentdependencies); } /** * Test the behaviour of loadContentDependencies() when requesting content dependencies * with specifying the dependency type. */ public function test_loadContentDependencies_type_defined() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(); // The Id of the h5p content. $h5pid = $data->h5pcontent->h5pid; // The content dependencies. $dependencies = $data->h5pcontent->contentdependencies; // Add Library5 as a content dependency (dynamic dependency type). $library5 = $data->lib5->data; $generator->create_contents_libraries_record($h5pid, $library5->id, 'dynamic'); // Load all content dependencies of dependency type 'preloaded'. $preloadeddependencies = $this->framework->loadContentDependencies($h5pid, 'preloaded'); $expected = array(); foreach ($dependencies as $dependency) { $expected[$dependency->machinename] = array( 'libraryId' => $dependency->id, 'machineName' => $dependency->machinename, 'majorVersion' => $dependency->majorversion, 'minorVersion' => $dependency->minorversion, 'patchVersion' => $dependency->patchversion, 'preloadedCss' => $dependency->preloadedcss, 'preloadedJs' => $dependency->preloadedjs, 'dropCss' => '0', 'dependencyType' => 'preloaded' ); } // The loaded content dependencies should return 5 libraries. $this->assertCount(5, $preloadeddependencies); $this->assertEquals($expected, $preloadeddependencies); // Load all content dependencies of dependency type 'dynamic'. $dynamicdependencies = $this->framework->loadContentDependencies($h5pid, 'dynamic'); $expected = array( 'Library5' => array( 'libraryId' => $library5->id, 'machineName' => $library5->machinename, 'majorVersion' => $library5->majorversion, 'minorVersion' => $library5->minorversion, 'patchVersion' => $library5->patchversion, 'preloadedCss' => $library5->preloadedcss, 'preloadedJs' => $library5->preloadedjs, 'dropCss' => '0', 'dependencyType' => 'dynamic' ) ); // The loaded content dependencies should now return 1 library. $this->assertCount(1, $dynamicdependencies); $this->assertEquals($expected, $dynamicdependencies); } /** * Test the behaviour of getOption(). */ public function test_getOption(): void { $this->resetAfterTest(); // Get value for display_option_download. $value = $this->framework->getOption(\H5PCore::DISPLAY_OPTION_DOWNLOAD); $expected = \H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_OFF; $this->assertEquals($expected, $value); // Get value for display_option_embed using default value (it should be ignored). $value = $this->framework->getOption(\H5PCore::DISPLAY_OPTION_EMBED, \H5PDisplayOptionBehaviour::NEVER_SHOW); $expected = \H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_OFF; $this->assertEquals($expected, $value); // Get value for unexisting setting without default. $value = $this->framework->getOption('unexistingsetting'); $expected = false; $this->assertEquals($expected, $value); // Get value for unexisting setting with default. $value = $this->framework->getOption('unexistingsetting', 'defaultvalue'); $expected = 'defaultvalue'; $this->assertEquals($expected, $value); } /** * Test the behaviour of setOption(). */ public function test_setOption(): void { $this->resetAfterTest(); // Set value for 'newsetting' setting. $name = 'newsetting'; $value = $this->framework->getOption($name); $this->assertEquals(false, $value); $newvalue = 'value1'; $this->framework->setOption($name, $newvalue); $value = $this->framework->getOption($name); $this->assertEquals($newvalue, $value); // Set value for display_option_download and then get it again. Check it hasn't changed. $name = \H5PCore::DISPLAY_OPTION_DOWNLOAD; $newvalue = \H5PDisplayOptionBehaviour::NEVER_SHOW; $this->framework->setOption($name, $newvalue); $value = $this->framework->getOption($name); $expected = \H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_OFF; $this->assertEquals($expected, $value); } /** * Test the behaviour of updateContentFields(). */ public function test_updateContentFields() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create 'Library1' library. $library1 = $generator->create_library_record('Library1', 'Lib1', 1, 1, 2); // Create 'Library2' library. $library2 = $generator->create_library_record('Library2', 'Lib2', 1, 1, 2); // Create an h5p content with 'Library1' as it's main library. $h5pid = $generator->create_h5p_record($library1->id, 'iframe'); $updatedata = array( 'jsoncontent' => json_encode(['value' => 'test']), 'mainlibraryid' => $library2->id ); // Update h5p content fields. $this->framework->updateContentFields($h5pid, $updatedata); // Get the h5p content from the DB. $h5p = $DB->get_record('h5p', ['id' => $h5pid]); $expected = json_encode(['value' => 'test']); // Make sure the h5p content fields are properly updated. $this->assertEquals($expected, $h5p->jsoncontent); $this->assertEquals($library2->id, $h5p->mainlibraryid); } /** * Test the behaviour of clearFilteredParameters(). */ public function test_clearFilteredParameters() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create 3 libraries. $library1 = $generator->create_library_record('Library1', 'Lib1', 1, 1, 2); $library2 = $generator->create_library_record('Library2', 'Lib2', 1, 1, 2); $library3 = $generator->create_library_record('Library3', 'Lib3', 1, 1, 2); // Create h5p content with 'Library1' as a main library. $h5pcontentid1 = $generator->create_h5p_record($library1->id); // Create h5p content with 'Library1' as a main library. $h5pcontentid2 = $generator->create_h5p_record($library1->id); // Create h5p content with 'Library2' as a main library. $h5pcontentid3 = $generator->create_h5p_record($library2->id); // Create h5p content with 'Library3' as a main library. $h5pcontentid4 = $generator->create_h5p_record($library3->id); $h5pcontent1 = $DB->get_record('h5p', ['id' => $h5pcontentid1]); $h5pcontent2 = $DB->get_record('h5p', ['id' => $h5pcontentid2]); $h5pcontent3 = $DB->get_record('h5p', ['id' => $h5pcontentid3]); $h5pcontent4 = $DB->get_record('h5p', ['id' => $h5pcontentid4]); // The filtered parameters should be present in each h5p content. $this->assertNotEmpty($h5pcontent1->filtered); $this->assertNotEmpty($h5pcontent2->filtered); $this->assertNotEmpty($h5pcontent3->filtered); $this->assertNotEmpty($h5pcontent4->filtered); // Clear the filtered parameters for contents that have library1 and library3 as // their main library. $this->framework->clearFilteredParameters([$library1->id, $library3->id]); $h5pcontent1 = $DB->get_record('h5p', ['id' => $h5pcontentid1]); $h5pcontent2 = $DB->get_record('h5p', ['id' => $h5pcontentid2]); $h5pcontent3 = $DB->get_record('h5p', ['id' => $h5pcontentid3]); $h5pcontent4 = $DB->get_record('h5p', ['id' => $h5pcontentid4]); // The filtered parameters should be still present only for the content that has // library 2 as a main library. $this->assertEmpty($h5pcontent1->filtered); $this->assertEmpty($h5pcontent2->filtered); $this->assertNotEmpty($h5pcontent3->filtered); $this->assertEmpty($h5pcontent4->filtered); } /** * Test the behaviour of getNumNotFiltered(). */ public function test_getNumNotFiltered() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create 3 libraries. $library1 = $generator->create_library_record('Library1', 'Lib1', 1, 1, 2); $library2 = $generator->create_library_record('Library2', 'Lib2', 1, 1, 2); $library3 = $generator->create_library_record('Library3', 'Lib3', 1, 1, 2); // Create h5p content with library1 as a main library. $h5pcontentid1 = $generator->create_h5p_record($library1->id); // Create h5p content with library1 as a main library. $h5pcontentid2 = $generator->create_h5p_record($library1->id); // Create h5p content with library2 as a main library. $h5pcontentid3 = $generator->create_h5p_record($library2->id); // Create h5p content with library3 as a main library. $h5pcontentid4 = $generator->create_h5p_record($library3->id); $h5pcontent1 = $DB->get_record('h5p', ['id' => $h5pcontentid1]); $h5pcontent2 = $DB->get_record('h5p', ['id' => $h5pcontentid2]); $h5pcontent3 = $DB->get_record('h5p', ['id' => $h5pcontentid3]); $h5pcontent4 = $DB->get_record('h5p', ['id' => $h5pcontentid4]); // The filtered parameters should be present in each h5p content. $this->assertNotEmpty($h5pcontent1->filtered); $this->assertNotEmpty($h5pcontent2->filtered); $this->assertNotEmpty($h5pcontent3->filtered); $this->assertNotEmpty($h5pcontent4->filtered); // Clear the filtered parameters for contents that have library1 and library3 as // their main library. $this->framework->clearFilteredParameters([$library1->id, $library3->id]); $countnotfiltered = $this->framework->getNumNotFiltered(); // 3 contents don't have their parameters filtered. $this->assertEquals(3, $countnotfiltered); } /** * Test the behaviour of getNumContent(). */ public function test_getNumContent() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(); // The 'MainLibrary' library data. $mainlibrary = $data->mainlib->data; // The 'Library1' library data. $library1 = $data->lib1->data; // Create new h5p content with MainLibrary as a main library. $generator->create_h5p_record($mainlibrary->id); // Get the number of h5p contents that are using 'MainLibrary' as their main library. $countmainlib = $this->framework->getNumContent($mainlibrary->id); // Get the number of h5p contents that are using 'Library1' as their main library. $countlib1 = $this->framework->getNumContent($library1->id); // Make sure that 2 contents are using MainLibrary as their main library. $this->assertEquals(2, $countmainlib); // Make sure that 0 contents are using Library1 as their main library. $this->assertEquals(0, $countlib1); } /** * Test the behaviour of getNumContent() when certain contents are being skipped. */ public function test_getNumContent_skip_content() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(); // The 'MainLibrary' library data. $mainlibrary = $data->mainlib->data; // Create new h5p content with MainLibrary as a main library. $h5pcontentid = $generator->create_h5p_record($mainlibrary->id); // Get the number of h5p contents that are using 'MainLibrary' as their main library. // Skip the newly created content $h5pcontentid. $countmainlib = $this->framework->getNumContent($mainlibrary->id, [$h5pcontentid]); // Make sure that 1 content is returned instead of 2 ($h5pcontentid being skipped). $this->assertEquals(1, $countmainlib); } /** * Test the behaviour of isContentSlugAvailable(). */ public function test_isContentSlugAvailable() { $this->resetAfterTest(); $slug = 'h5p-test-slug-1'; // Currently this returns always true. The slug is generated as a unique value for // each h5p content and it is not stored in the h5p content table. $isslugavailable = $this->framework->isContentSlugAvailable($slug); $this->assertTrue($isslugavailable); } /** * Test that a record is stored for cached assets. */ public function test_saveCachedAssets() { global $DB; $this->resetAfterTest(); $libraries = array( array( 'machineName' => 'H5P.TestLib', 'libraryId' => 405, ), array( 'FontAwesome' => 'FontAwesome', 'libraryId' => 406, ), array( 'machineName' => 'H5P.SecondLib', 'libraryId' => 407, ), ); $key = 'testhashkey'; $this->framework->saveCachedAssets($key, $libraries); $records = $DB->get_records('h5p_libraries_cachedassets'); $this->assertCount(3, $records); } /** * Test that the correct libraries are removed from the cached assets table */ public function test_deleteCachedAssets() { global $DB; $this->resetAfterTest(); $libraries = array( array( 'machineName' => 'H5P.TestLib', 'libraryId' => 405, ), array( 'FontAwesome' => 'FontAwesome', 'libraryId' => 406, ), array( 'machineName' => 'H5P.SecondLib', 'libraryId' => 407, ), ); $key1 = 'testhashkey'; $this->framework->saveCachedAssets($key1, $libraries); $libraries = array( array( 'machineName' => 'H5P.DiffLib', 'libraryId' => 408, ), array( 'FontAwesome' => 'FontAwesome', 'libraryId' => 406, ), array( 'machineName' => 'H5P.ThirdLib', 'libraryId' => 409, ), ); $key2 = 'secondhashkey'; $this->framework->saveCachedAssets($key2, $libraries); $libraries = array( array( 'machineName' => 'H5P.AnotherDiffLib', 'libraryId' => 410, ), array( 'FontAwesome' => 'NotRelated', 'libraryId' => 411, ), array( 'machineName' => 'H5P.ForthLib', 'libraryId' => 412, ), ); $key3 = 'threeforthewin'; $this->framework->saveCachedAssets($key3, $libraries); $records = $DB->get_records('h5p_libraries_cachedassets'); $this->assertCount(9, $records); // Selecting one library id will result in all related library entries also being deleted. // Going to use the FontAwesome library id. The first two hashes should be returned. $hashes = $this->framework->deleteCachedAssets(406); $this->assertCount(2, $hashes); $index = array_search($key1, $hashes); $this->assertEquals($key1, $hashes[$index]); $index = array_search($key2, $hashes); $this->assertEquals($key2, $hashes[$index]); $index = array_search($key3, $hashes); $this->assertFalse($index); // Check that the records have been removed as well. $records = $DB->get_records('h5p_libraries_cachedassets'); $this->assertCount(3, $records); } /** * Test the behaviour of getLibraryContentCount(). */ public function test_getLibraryContentCount() { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Generate h5p related data. $data = $generator->generate_h5p_data(); // The 'MainLibrary' library data. $mainlibrary = $data->mainlib->data; // The 'Library2' library data. $library2 = $data->lib2->data; // Create new h5p content with Library2 as it's main library. $generator->create_h5p_record($library2->id); // Create new h5p content with MainLibrary as it's main library. $generator->create_h5p_record($mainlibrary->id); $countlibrarycontent = $this->framework->getLibraryContentCount(); $expected = array( "{$mainlibrary->machinename} {$mainlibrary->majorversion}.{$mainlibrary->minorversion}" => 2, "{$library2->machinename} {$library2->majorversion}.{$library2->minorversion}" => 1, ); // MainLibrary and Library1 are currently main libraries to the existing h5p contents. // Should return the number of cases where MainLibrary and Library1 are main libraries to an h5p content. $this->assertEquals($expected, $countlibrarycontent); } /** * Test the behaviour of test_libraryHasUpgrade(). * * @dataProvider test_libraryHasUpgrade_provider * @param array $libraryrecords Array containing data for the library creation * @param array $testlibrary Array containing the test library data * @param bool $expected The expectation whether the library is patched or not **/ public function test_libraryHasUpgrade(array $libraryrecords, array $testlibrary, bool $expected): void { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); foreach ($libraryrecords as $library) { call_user_func_array([$generator, 'create_library_record'], $library); } $this->assertEquals($expected, $this->framework->libraryHasUpgrade($testlibrary)); } /** * Data provider for test_libraryHasUpgrade(). * * @return array */ public function test_libraryHasUpgrade_provider(): array { return [ 'Lower major version; Identical lower version' => [ [ ['Library', 'Lib', 2, 2], ], [ 'machineName' => 'Library', 'majorVersion' => 1, 'minorVersion' => 2 ], true, ], 'Major version identical; Lower minor version' => [ [ ['Library', 'Lib', 2, 2], ], [ 'machineName' => 'Library', 'majorVersion' => 2, 'minorVersion' => 1 ], true, ], 'Major version identical; Minor version identical' => [ [ ['Library', 'Lib', 2, 2], ], [ 'machineName' => 'Library', 'majorVersion' => 2, 'minorVersion' => 2 ], false, ], 'Major version higher; Minor version identical' => [ [ ['Library', 'Lib', 2, 2], ], [ 'machineName' => 'Library', 'majorVersion' => 3, 'minorVersion' => 2 ], false, ], 'Major version identical; Minor version newer' => [ [ ['Library', 'Lib', 2, 2], ], [ 'machineName' => 'Library', 'majorVersion' => 2, 'minorVersion' => 4 ], false, ] ]; } /** * Test the behaviour of get_latest_library_version(). */ public function test_get_latest_library_version() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); // Create a library record. $machinename = 'TestLibrary'; $lib1 = $generator->create_library_record($machinename, 'Test', 1, 1, 2); $lib2 = $generator->create_library_record($machinename, 'Test', 1, 2, 1); $content = array( 'params' => json_encode(['param1' => 'Test']), 'library' => array( 'libraryId' => 0, 'machineName' => 'TestLibrary', ), 'disable' => 8 ); // Get the latest id (at this point, should be lib2). $latestlib = $this->framework->get_latest_library_version($machinename); $this->assertEquals($lib2->id, $latestlib->id); // Get the latest id (at this point, should be lib3). $lib3 = $generator->create_library_record($machinename, 'Test', 2, 1, 0); $latestlib = $this->framework->get_latest_library_version($machinename); $this->assertEquals($lib3->id, $latestlib->id); // Get the latest id (at this point, should be still lib3). $lib4 = $generator->create_library_record($machinename, 'Test', 1, 1, 3); $latestlib = $this->framework->get_latest_library_version($machinename); $this->assertEquals($lib3->id, $latestlib->id); // Get the latest id (at this point, should be lib5). $lib5 = $generator->create_library_record($machinename, 'Test', 2, 1, 6); $latestlib = $this->framework->get_latest_library_version($machinename); $this->assertEquals($lib5->id, $latestlib->id); } }