. namespace core_h5p; use core_h5p\local\library\autoloader; /** * Test class covering the h5p data generator class. * * @package core_h5p * @category test * @copyright 2019 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @runTestsInSeparateProcesses * @covers \core_h5p_generator */ class generator_test extends \advanced_testcase { /** * Tests set up. */ protected function setUp(): void { parent::setUp(); autoloader::register(); } /** * Test the returned data of generate_h5p_data() when the method is called without requesting * creation of library files. */ public function test_generate_h5p_data_no_files_created_return_data(): void { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $data = $generator->generate_h5p_data(); $mainlib = $DB->get_record('h5p_libraries', ['machinename' => 'MainLibrary']); $lib1 = $DB->get_record('h5p_libraries', ['machinename' => 'Library1']); $lib2 = $DB->get_record('h5p_libraries', ['machinename' => 'Library2']); $lib3 = $DB->get_record('h5p_libraries', ['machinename' => 'Library3']); $lib4 = $DB->get_record('h5p_libraries', ['machinename' => 'Library4']); $lib5 = $DB->get_record('h5p_libraries', ['machinename' => 'Library5']); $h5p = $DB->get_record('h5p', ['mainlibraryid' => $mainlib->id]); $expected = (object) [ 'h5pcontent' => (object) array( 'h5pid' => $h5p->id, 'contentdependencies' => array($mainlib, $lib1, $lib2, $lib3, $lib4) ), 'mainlib' => (object) array( 'data' => $mainlib, 'dependencies' => array($lib1, $lib2, $lib3) ), 'lib1' => (object) array( 'data' => $lib1, 'dependencies' => array($lib2, $lib3, $lib4) ), 'lib2' => (object) array( 'data' => $lib2, 'dependencies' => array() ), 'lib3' => (object) array( 'data' => $lib3, 'dependencies' => array($lib5) ), 'lib4' => (object) array( 'data' => $lib4, 'dependencies' => array() ), 'lib5' => (object) array( 'data' => $lib5, 'dependencies' => array() ), ]; $this->assertEquals($expected, $data); } /** * Test the returned data of generate_h5p_data() when the method requests * creation of library files. */ public function test_generate_h5p_data_files_created_return_data(): void { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $data = $generator->generate_h5p_data(true); $mainlib = $DB->get_record('h5p_libraries', ['machinename' => 'MainLibrary']); $lib1 = $DB->get_record('h5p_libraries', ['machinename' => 'Library1']); $lib2 = $DB->get_record('h5p_libraries', ['machinename' => 'Library2']); $lib3 = $DB->get_record('h5p_libraries', ['machinename' => 'Library3']); $lib4 = $DB->get_record('h5p_libraries', ['machinename' => 'Library4']); $lib5 = $DB->get_record('h5p_libraries', ['machinename' => 'Library5']); $h5p = $DB->get_record('h5p', ['mainlibraryid' => $mainlib->id]); $expected = (object) [ 'h5pcontent' => (object) array( 'h5pid' => $h5p->id, 'contentdependencies' => array($mainlib, $lib1, $lib2, $lib3, $lib4) ), 'mainlib' => (object) array( 'data' => $mainlib, 'dependencies' => array($lib1, $lib2, $lib3) ), 'lib1' => (object) array( 'data' => $lib1, 'dependencies' => array($lib2, $lib3, $lib4) ), 'lib2' => (object) array( 'data' => $lib2, 'dependencies' => array() ), 'lib3' => (object) array( 'data' => $lib3, 'dependencies' => array($lib5) ), 'lib4' => (object) array( 'data' => $lib4, 'dependencies' => array() ), 'lib5' => (object) array( 'data' => $lib5, 'dependencies' => array() ), ]; $this->assertEquals($expected, $data); } /** * Test the behaviour of generate_h5p_data(). Test whether library files are created or not * on filesystem depending what the method defines. * * @dataProvider generate_h5p_data_files_creation_provider * @param bool $createlibraryfiles Whether to create library files on the filesystem * @param bool $expected The expectation whether the files have been created or not **/ public function test_generate_h5p_data_files_creation(bool $createlibraryfiles, bool $expected): void { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $generator->generate_h5p_data($createlibraryfiles); $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'MainLibrary']); $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library1']); $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library2']); $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library3']); $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library4']); $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library5']); foreach($libraries as $lib) { // Return the created library files. $libraryfiles = $DB->get_records('files', array( 'component' => \core_h5p\file_storage::COMPONENT, 'filearea' => \core_h5p\file_storage::LIBRARY_FILEAREA, 'itemid' => $lib->id ) ); $haslibraryfiles = !empty($libraryfiles); $this->assertEquals($expected, $haslibraryfiles); } } /** * Data provider for test_generate_h5p_data_files_creation(). * * @return array */ public function generate_h5p_data_files_creation_provider(): array { return [ 'Do not create library related files on the filesystem' => [ false, false ], 'Create library related files on the filesystem' => [ true, true ] ]; } /** * Test the returned data of generate_h5p_data() when the method requests * creation of H5P file and xAPI states. * * @dataProvider generate_h5p_data_xapistates_provider * @param array|null $filerecord */ public function test_generate_h5p_data_xapistates(?array $filerecord): void { global $DB; $this->resetAfterTest(); /** @var \core_h5p_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $course = $this->getDataGenerator()->create_course(); $user = $this->getDataGenerator()->create_and_enrol($course, 'student'); $this->setUser($user); $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]); $activitycontext = \context_module::instance($activity->cmid); if ($filerecord) { $filerecord['contextid'] = $activitycontext->id; $filerecord['component'] = 'mod_h5pactivity'; $filerecord['filearea'] = 'package'; $filerecord['itemid'] = 0; $filerecord['filepath'] = '/'; $filerecord['filepath'] = '/'; $filerecord['filename'] = 'dummy.h5p'; } $data = $generator->generate_h5p_data(false, $filerecord); $mainlib = $DB->get_record('h5p_libraries', ['machinename' => 'MainLibrary']); $lib1 = $DB->get_record('h5p_libraries', ['machinename' => 'Library1']); $lib2 = $DB->get_record('h5p_libraries', ['machinename' => 'Library2']); $lib3 = $DB->get_record('h5p_libraries', ['machinename' => 'Library3']); $lib4 = $DB->get_record('h5p_libraries', ['machinename' => 'Library4']); $lib5 = $DB->get_record('h5p_libraries', ['machinename' => 'Library5']); $h5p = $DB->get_record('h5p', ['mainlibraryid' => $mainlib->id]); $expected = (object) [ 'h5pcontent' => (object) [ 'h5pid' => $h5p->id, 'contentdependencies' => [$mainlib, $lib1, $lib2, $lib3, $lib4], ], 'mainlib' => (object) [ 'data' => $mainlib, 'dependencies' => [$lib1, $lib2, $lib3], ], 'lib1' => (object) [ 'data' => $lib1, 'dependencies' => [$lib2, $lib3, $lib4], ], 'lib2' => (object) [ 'data' => $lib2, 'dependencies' => [], ], 'lib3' => (object) [ 'data' => $lib3, 'dependencies' => [$lib5], ], 'lib4' => (object) [ 'data' => $lib4, 'dependencies' => [], ], 'lib5' => (object) [ 'data' => $lib5, 'dependencies' => [], ], ]; $this->assertEquals($expected, $data); if ($filerecord) { // Confirm the H5P file has been created (when $filerecord is not empty). $fs = get_file_storage(); $this->assertNotFalse($fs->get_file_by_hash($h5p->pathnamehash)); // Confirm xAPI state has been created when $filerecord['addxapistate'] is given. if (array_key_exists('addxapistate', $filerecord) && $filerecord['addxapistate']) { $this->assertEquals(1, $DB->count_records('xapi_states')); } else { $this->assertEquals(0, $DB->count_records('xapi_states')); } } else { // Confirm the H5P file doesn't exist when $filerecord is null. $fs = get_file_storage(); $this->assertFalse($fs->get_file_by_hash($h5p->pathnamehash)); // Confirm xAPI state hasn't been created when $filerecord is null. $this->assertEquals(0, $DB->count_records('xapi_states')); } } /** * Data provider for test_generate_h5p_data_xapistates(). * * @return array */ public function generate_h5p_data_xapistates_provider(): array { return [ 'Do not create the file nor xAPI states' => [ 'filerecord' => null, ], 'Create the H5P file but not create any xAPI state' => [ 'filerecord' => [ 'addxapistate' => false, ], ], 'Create the H5P file and the xAPI state' => [ 'filerecord' => [ 'addxapistate' => true, ], ], ]; } /** * Test the behaviour of create_library_record(). Test whether the library data is properly * saved in the database. */ public function test_create_library_record(): void { $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $data = $generator->create_library_record( 'Library', 'Lib', 1, 2, 3, 'Semantics example', '/regex11/', 'http://tutorial.org/', 'http://example.org/' ); unset($data->id); $expected = (object) [ 'machinename' => 'Library', 'title' => 'Lib', 'majorversion' => '1', 'minorversion' => '2', 'patchversion' => '3', 'runnable' => '1', 'fullscreen' => '1', 'embedtypes' => '', 'preloadedjs' => 'js/example.js', 'preloadedcss' => 'css/example.css', 'droplibrarycss' => '', 'semantics' => 'Semantics example', 'addto' => '/regex11/', 'tutorial' => 'http://tutorial.org/', 'example' => 'http://example.org/', 'coremajor' => null, 'coreminor' => null, 'metadatasettings' => null, 'enabled' => 1, ]; $this->assertEquals($expected, $data); } /** * Test the behaviour of create_h5p_record(). Test whather the h5p content data is * properly saved in the database. * * @dataProvider create_h5p_record_provider * @param array $h5pdata The h5p content data * @param \stdClass $expected The expected saved data **/ public function test_create_h5p_record(array $h5pdata, \stdClass $expected): void { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $h5pid = call_user_func_array([$generator, 'create_h5p_record'], $h5pdata); $data = $DB->get_record('h5p', ['id' => $h5pid]); unset($data->id); unset($data->timecreated); unset($data->timemodified); $this->assertEquals($data, $expected); } /** * Data provider for test_create_h5p_record(). * * @return array */ public function create_h5p_record_provider(): array { $createdjsoncontent = json_encode( array( 'text' => '

Created dummy text<\/p>\n', 'questions' => '

Test created question<\/p>\n' ) ); $defaultjsoncontent = json_encode( array( 'text' => '

Dummy text<\/p>\n', 'questions' => '

Test question<\/p>\n' ) ); $createdfilteredcontent = json_encode( array( 'text' => 'Created dummy text', 'questions' => 'Test created question' ) ); $defaultfilteredcontent = json_encode( array( 'text' => 'Dummy text', 'questions' => 'Test question' ) ); return [ 'Create h5p content record with set json content and set filtered content' => [ [ 1, $createdjsoncontent, $createdfilteredcontent ], (object) array( 'jsoncontent' => $createdjsoncontent, 'mainlibraryid' => '1', 'displayoptions' => '8', 'pathnamehash' => sha1('pathname'), 'contenthash' => sha1('content'), 'filtered' => $createdfilteredcontent, ) ], 'Create h5p content record with set json content and default filtered content' => [ [ 1, $createdjsoncontent, null ], (object) array( 'jsoncontent' => $createdjsoncontent, 'mainlibraryid' => '1', 'displayoptions' => '8', 'pathnamehash' => sha1('pathname'), 'contenthash' => sha1('content'), 'filtered' => $defaultfilteredcontent, ) ], 'Create h5p content record with default json content and set filtered content' => [ [ 1, null, $createdfilteredcontent ], (object) array( 'jsoncontent' => $defaultjsoncontent, 'mainlibraryid' => '1', 'displayoptions' => '8', 'pathnamehash' => sha1('pathname'), 'contenthash' => sha1('content'), 'filtered' => $createdfilteredcontent, ) ], 'Create h5p content record with default json content and default filtered content' => [ [ 1, null, null ], (object) array( 'jsoncontent' => $defaultjsoncontent, 'mainlibraryid' => '1', 'displayoptions' => '8', 'pathnamehash' => sha1('pathname'), 'contenthash' => sha1('content'), 'filtered' => $defaultfilteredcontent, ) ] ]; } /** * Test the behaviour of create_contents_libraries_record(). Test whether the contents libraries * are properly saved in the database. * * @dataProvider create_contents_libraries_record_provider * @param array $contentslibrariestdata The h5p contents libraries data. * @param \stdClass $expected The expected saved data. **/ public function test_create_contents_libraries_record(array $contentslibrariestdata, \stdClass $expected): void { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $contentlibid = call_user_func_array([$generator, 'create_contents_libraries_record'], $contentslibrariestdata); $data = $DB->get_record('h5p_contents_libraries', ['id' => $contentlibid]); unset($data->id); $this->assertEquals($data, $expected); } /** * Data provider for test_create_contents_libraries_record(). * * @return array */ public function create_contents_libraries_record_provider(): array { return [ 'Create h5p content library with set dependency type' => [ [ 1, 1, 'dynamic' ], (object) array( 'h5pid' => '1', 'libraryid' => '1', 'dependencytype' => 'dynamic', 'dropcss' => '0', 'weight' => '1' ) ], 'Create h5p content library with a default dependency type' => [ [ 1, 1 ], (object) array( 'h5pid' => '1', 'libraryid' => '1', 'dependencytype' => 'preloaded', 'dropcss' => '0', 'weight' => '1' ) ] ]; } /** * Test the behaviour of create_library_dependency_record(). Test whether the contents libraries * are properly saved in the database. * * @dataProvider create_library_dependency_record_provider * @param array $librarydependencydata The library dependency data. * @param \stdClass $expected The expected saved data. **/ public function test_create_library_dependency_record(array $librarydependencydata, \stdClass $expected): void { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $contentlibid = call_user_func_array([$generator, 'create_library_dependency_record'], $librarydependencydata); $data = $DB->get_record('h5p_library_dependencies', ['id' => $contentlibid]); unset($data->id); $this->assertEquals($data, $expected); } /** * Data provider for test_create_library_dependency_record(). * * @return array */ public function create_library_dependency_record_provider(): array { return [ 'Create h5p library dependency with set dependency type' => [ [ 1, 1, 'dynamic' ], (object) array( 'libraryid' => '1', 'requiredlibraryid' => '1', 'dependencytype' => 'dynamic' ) ], 'Create h5p library dependency with default dependency type' => [ [ 1, 1 ], (object) array( 'libraryid' => '1', 'requiredlibraryid' => '1', 'dependencytype' => 'preloaded' ) ] ]; } /** * Test the behaviour of create_content_file(). Test whether a file belonging to a content is created. * * @dataProvider create_content_file_provider * @param array $filedata Data from the file to be created. * @param array $expecteddata Data expected.Data from the file to be created. */ public function test_create_content_file($filedata, $expecteddata): void { $this->resetAfterTest(); $generator = self::getDataGenerator()->get_plugin_generator('core_h5p'); if ($expecteddata[1] === 'exception') { $this->expectException('coding_exception'); } call_user_func_array([$generator, 'create_content_file'], $filedata); $systemcontext = \context_system::instance(); $filearea = $filedata[1]; $filepath = '/'. dirname($filedata[0]). '/'; $filename = basename($filedata[0]); $itemid = $expecteddata[0]; $fs = new \file_storage(); $exists = $fs->file_exists($systemcontext->id, file_storage::COMPONENT, $filearea, $itemid, $filepath, $filename); if ($expecteddata[1] === true) { $this->assertTrue($exists); } else if ($expecteddata[1] === false) { $this->assertFalse($exists); } } /** * Data provider for test_create_content_file(). Data from different files to be created. * * @return array **/ public function create_content_file_provider(): array { return [ 'Create file in content with id 4' => [ [ 'images/img1.png', 'content', 4 ], [ 4, true ] ], 'Create file in the editor' => [ [ 'images/img1.png', 'editor' ], [ 0, true ] ], 'Create file in content without id' => [ [ 'images/img1.png', 'content' ], [ 0, 'exception' ] ] ]; } }