Merge branch 'MDL-78457' of https://github.com/paulholden/moodle
[moodle.git] / h5p / tests / generator_test.php
blob623bf3cd220e5ba708f2b3febfe5364cad9e9640
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 namespace core_h5p;
19 use core_h5p\local\library\autoloader;
21 /**
22 * Test class covering the h5p data generator class.
24 * @package core_h5p
25 * @category test
26 * @copyright 2019 Mihail Geshoski <mihail@moodle.com>
27 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 * @runTestsInSeparateProcesses
29 * @covers \core_h5p_generator
31 class generator_test extends \advanced_testcase {
33 /**
34 * Tests set up.
36 protected function setUp(): void {
37 parent::setUp();
39 autoloader::register();
42 /**
43 * Test the returned data of generate_h5p_data() when the method is called without requesting
44 * creation of library files.
46 public function test_generate_h5p_data_no_files_created_return_data() {
47 global $DB;
49 $this->resetAfterTest();
51 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
53 $data = $generator->generate_h5p_data();
55 $mainlib = $DB->get_record('h5p_libraries', ['machinename' => 'MainLibrary']);
56 $lib1 = $DB->get_record('h5p_libraries', ['machinename' => 'Library1']);
57 $lib2 = $DB->get_record('h5p_libraries', ['machinename' => 'Library2']);
58 $lib3 = $DB->get_record('h5p_libraries', ['machinename' => 'Library3']);
59 $lib4 = $DB->get_record('h5p_libraries', ['machinename' => 'Library4']);
60 $lib5 = $DB->get_record('h5p_libraries', ['machinename' => 'Library5']);
62 $h5p = $DB->get_record('h5p', ['mainlibraryid' => $mainlib->id]);
64 $expected = (object) [
65 'h5pcontent' => (object) array(
66 'h5pid' => $h5p->id,
67 'contentdependencies' => array($mainlib, $lib1, $lib2, $lib3, $lib4)
69 'mainlib' => (object) array(
70 'data' => $mainlib,
71 'dependencies' => array($lib1, $lib2, $lib3)
73 'lib1' => (object) array(
74 'data' => $lib1,
75 'dependencies' => array($lib2, $lib3, $lib4)
77 'lib2' => (object) array(
78 'data' => $lib2,
79 'dependencies' => array()
81 'lib3' => (object) array(
82 'data' => $lib3,
83 'dependencies' => array($lib5)
85 'lib4' => (object) array(
86 'data' => $lib4,
87 'dependencies' => array()
89 'lib5' => (object) array(
90 'data' => $lib5,
91 'dependencies' => array()
95 $this->assertEquals($expected, $data);
98 /**
99 * Test the returned data of generate_h5p_data() when the method requests
100 * creation of library files.
102 public function test_generate_h5p_data_files_created_return_data() {
103 global $DB;
105 $this->resetAfterTest();
107 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
109 $data = $generator->generate_h5p_data(true);
111 $mainlib = $DB->get_record('h5p_libraries', ['machinename' => 'MainLibrary']);
112 $lib1 = $DB->get_record('h5p_libraries', ['machinename' => 'Library1']);
113 $lib2 = $DB->get_record('h5p_libraries', ['machinename' => 'Library2']);
114 $lib3 = $DB->get_record('h5p_libraries', ['machinename' => 'Library3']);
115 $lib4 = $DB->get_record('h5p_libraries', ['machinename' => 'Library4']);
116 $lib5 = $DB->get_record('h5p_libraries', ['machinename' => 'Library5']);
118 $h5p = $DB->get_record('h5p', ['mainlibraryid' => $mainlib->id]);
120 $expected = (object) [
121 'h5pcontent' => (object) array(
122 'h5pid' => $h5p->id,
123 'contentdependencies' => array($mainlib, $lib1, $lib2, $lib3, $lib4)
125 'mainlib' => (object) array(
126 'data' => $mainlib,
127 'dependencies' => array($lib1, $lib2, $lib3)
129 'lib1' => (object) array(
130 'data' => $lib1,
131 'dependencies' => array($lib2, $lib3, $lib4)
133 'lib2' => (object) array(
134 'data' => $lib2,
135 'dependencies' => array()
137 'lib3' => (object) array(
138 'data' => $lib3,
139 'dependencies' => array($lib5)
141 'lib4' => (object) array(
142 'data' => $lib4,
143 'dependencies' => array()
145 'lib5' => (object) array(
146 'data' => $lib5,
147 'dependencies' => array()
151 $this->assertEquals($expected, $data);
155 * Test the behaviour of generate_h5p_data(). Test whether library files are created or not
156 * on filesystem depending what the method defines.
158 * @dataProvider generate_h5p_data_files_creation_provider
159 * @param bool $createlibraryfiles Whether to create library files on the filesystem
160 * @param bool $expected The expectation whether the files have been created or not
162 public function test_generate_h5p_data_files_creation(bool $createlibraryfiles, bool $expected) {
163 global $DB;
165 $this->resetAfterTest();
167 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
168 $generator->generate_h5p_data($createlibraryfiles);
170 $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'MainLibrary']);
171 $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library1']);
172 $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library2']);
173 $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library3']);
174 $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library4']);
175 $libraries[] = $DB->get_record('h5p_libraries', ['machinename' => 'Library5']);
177 foreach($libraries as $lib) {
178 // Return the created library files.
179 $libraryfiles = $DB->get_records('files',
180 array(
181 'component' => \core_h5p\file_storage::COMPONENT,
182 'filearea' => \core_h5p\file_storage::LIBRARY_FILEAREA,
183 'itemid' => $lib->id
187 $haslibraryfiles = !empty($libraryfiles);
189 $this->assertEquals($expected, $haslibraryfiles);
194 * Data provider for test_generate_h5p_data_files_creation().
196 * @return array
198 public function generate_h5p_data_files_creation_provider(): array {
199 return [
200 'Do not create library related files on the filesystem' => [
201 false,
202 false
204 'Create library related files on the filesystem' => [
205 true,
206 true
212 * Test the returned data of generate_h5p_data() when the method requests
213 * creation of H5P file and xAPI states.
215 * @dataProvider generate_h5p_data_xapistates_provider
216 * @param array|null $filerecord
218 public function test_generate_h5p_data_xapistates(?array $filerecord) {
219 global $DB;
221 $this->resetAfterTest();
223 /** @var \core_h5p_generator $generator */
224 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
225 $course = $this->getDataGenerator()->create_course();
226 $user = $this->getDataGenerator()->create_and_enrol($course, 'student');
227 $this->setUser($user);
228 $activity = $this->getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
229 $activitycontext = \context_module::instance($activity->cmid);
230 if ($filerecord) {
231 $filerecord['contextid'] = $activitycontext->id;
232 $filerecord['component'] = 'mod_h5pactivity';
233 $filerecord['filearea'] = 'package';
234 $filerecord['itemid'] = 0;
235 $filerecord['filepath'] = '/';
236 $filerecord['filepath'] = '/';
237 $filerecord['filename'] = 'dummy.h5p';
240 $data = $generator->generate_h5p_data(false, $filerecord);
242 $mainlib = $DB->get_record('h5p_libraries', ['machinename' => 'MainLibrary']);
243 $lib1 = $DB->get_record('h5p_libraries', ['machinename' => 'Library1']);
244 $lib2 = $DB->get_record('h5p_libraries', ['machinename' => 'Library2']);
245 $lib3 = $DB->get_record('h5p_libraries', ['machinename' => 'Library3']);
246 $lib4 = $DB->get_record('h5p_libraries', ['machinename' => 'Library4']);
247 $lib5 = $DB->get_record('h5p_libraries', ['machinename' => 'Library5']);
249 $h5p = $DB->get_record('h5p', ['mainlibraryid' => $mainlib->id]);
251 $expected = (object) [
252 'h5pcontent' => (object) [
253 'h5pid' => $h5p->id,
254 'contentdependencies' => [$mainlib, $lib1, $lib2, $lib3, $lib4],
256 'mainlib' => (object) [
257 'data' => $mainlib,
258 'dependencies' => [$lib1, $lib2, $lib3],
260 'lib1' => (object) [
261 'data' => $lib1,
262 'dependencies' => [$lib2, $lib3, $lib4],
264 'lib2' => (object) [
265 'data' => $lib2,
266 'dependencies' => [],
268 'lib3' => (object) [
269 'data' => $lib3,
270 'dependencies' => [$lib5],
272 'lib4' => (object) [
273 'data' => $lib4,
274 'dependencies' => [],
276 'lib5' => (object) [
277 'data' => $lib5,
278 'dependencies' => [],
282 $this->assertEquals($expected, $data);
283 if ($filerecord) {
284 // Confirm the H5P file has been created (when $filerecord is not empty).
285 $fs = get_file_storage();
286 $this->assertNotFalse($fs->get_file_by_hash($h5p->pathnamehash));
287 // Confirm xAPI state has been created when $filerecord['addxapistate'] is given.
288 if (array_key_exists('addxapistate', $filerecord) && $filerecord['addxapistate']) {
289 $this->assertEquals(1, $DB->count_records('xapi_states'));
290 } else {
291 $this->assertEquals(0, $DB->count_records('xapi_states'));
293 } else {
294 // Confirm the H5P file doesn't exist when $filerecord is null.
295 $fs = get_file_storage();
296 $this->assertFalse($fs->get_file_by_hash($h5p->pathnamehash));
297 // Confirm xAPI state hasn't been created when $filerecord is null.
298 $this->assertEquals(0, $DB->count_records('xapi_states'));
303 * Data provider for test_generate_h5p_data_xapistates().
305 * @return array
307 public function generate_h5p_data_xapistates_provider(): array {
308 return [
309 'Do not create the file nor xAPI states' => [
310 'filerecord' => null,
312 'Create the H5P file but not create any xAPI state' => [
313 'filerecord' => [
314 'addxapistate' => false,
317 'Create the H5P file and the xAPI state' => [
318 'filerecord' => [
319 'addxapistate' => true,
326 * Test the behaviour of create_library_record(). Test whether the library data is properly
327 * saved in the database.
329 public function test_create_library_record() {
330 $this->resetAfterTest();
332 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
334 $data = $generator->create_library_record(
335 'Library', 'Lib', 1, 2, 3, 'Semantics example', '/regex11/', 'http://tutorial.org/', 'http://example.org/'
337 unset($data->id);
339 $expected = (object) [
340 'machinename' => 'Library',
341 'title' => 'Lib',
342 'majorversion' => '1',
343 'minorversion' => '2',
344 'patchversion' => '3',
345 'runnable' => '1',
346 'fullscreen' => '1',
347 'embedtypes' => '',
348 'preloadedjs' => 'js/example.js',
349 'preloadedcss' => 'css/example.css',
350 'droplibrarycss' => '',
351 'semantics' => 'Semantics example',
352 'addto' => '/regex11/',
353 'tutorial' => 'http://tutorial.org/',
354 'example' => 'http://example.org/',
355 'coremajor' => null,
356 'coreminor' => null,
357 'metadatasettings' => null,
358 'enabled' => 1,
361 $this->assertEquals($expected, $data);
365 * Test the behaviour of create_h5p_record(). Test whather the h5p content data is
366 * properly saved in the database.
368 * @dataProvider create_h5p_record_provider
369 * @param array $h5pdata The h5p content data
370 * @param \stdClass $expected The expected saved data
372 public function test_create_h5p_record(array $h5pdata, \stdClass $expected) {
373 global $DB;
375 $this->resetAfterTest();
377 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
379 $h5pid = call_user_func_array([$generator, 'create_h5p_record'], $h5pdata);
381 $data = $DB->get_record('h5p', ['id' => $h5pid]);
382 unset($data->id);
383 unset($data->timecreated);
384 unset($data->timemodified);
386 $this->assertEquals($data, $expected);
390 * Data provider for test_create_h5p_record().
392 * @return array
394 public function create_h5p_record_provider(): array {
395 $createdjsoncontent = json_encode(
396 array(
397 'text' => '<p>Created dummy text<\/p>\n',
398 'questions' => '<p>Test created question<\/p>\n'
402 $defaultjsoncontent = json_encode(
403 array(
404 'text' => '<p>Dummy text<\/p>\n',
405 'questions' => '<p>Test question<\/p>\n'
409 $createdfilteredcontent = json_encode(
410 array(
411 'text' => 'Created dummy text',
412 'questions' => 'Test created question'
416 $defaultfilteredcontent = json_encode(
417 array(
418 'text' => 'Dummy text',
419 'questions' => 'Test question'
423 return [
424 'Create h5p content record with set json content and set filtered content' => [
427 $createdjsoncontent,
428 $createdfilteredcontent
430 (object) array(
431 'jsoncontent' => $createdjsoncontent,
432 'mainlibraryid' => '1',
433 'displayoptions' => '8',
434 'pathnamehash' => sha1('pathname'),
435 'contenthash' => sha1('content'),
436 'filtered' => $createdfilteredcontent,
439 'Create h5p content record with set json content and default filtered content' => [
442 $createdjsoncontent,
443 null
445 (object) array(
446 'jsoncontent' => $createdjsoncontent,
447 'mainlibraryid' => '1',
448 'displayoptions' => '8',
449 'pathnamehash' => sha1('pathname'),
450 'contenthash' => sha1('content'),
451 'filtered' => $defaultfilteredcontent,
454 'Create h5p content record with default json content and set filtered content' => [
457 null,
458 $createdfilteredcontent
460 (object) array(
461 'jsoncontent' => $defaultjsoncontent,
462 'mainlibraryid' => '1',
463 'displayoptions' => '8',
464 'pathnamehash' => sha1('pathname'),
465 'contenthash' => sha1('content'),
466 'filtered' => $createdfilteredcontent,
469 'Create h5p content record with default json content and default filtered content' => [
472 null,
473 null
475 (object) array(
476 'jsoncontent' => $defaultjsoncontent,
477 'mainlibraryid' => '1',
478 'displayoptions' => '8',
479 'pathnamehash' => sha1('pathname'),
480 'contenthash' => sha1('content'),
481 'filtered' => $defaultfilteredcontent,
488 * Test the behaviour of create_contents_libraries_record(). Test whether the contents libraries
489 * are properly saved in the database.
491 * @dataProvider create_contents_libraries_record_provider
492 * @param array $contentslibrariestdata The h5p contents libraries data.
493 * @param \stdClass $expected The expected saved data.
495 public function test_create_contents_libraries_record(array $contentslibrariestdata, \stdClass $expected) {
496 global $DB;
498 $this->resetAfterTest();
500 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
502 $contentlibid = call_user_func_array([$generator, 'create_contents_libraries_record'], $contentslibrariestdata);
504 $data = $DB->get_record('h5p_contents_libraries', ['id' => $contentlibid]);
505 unset($data->id);
507 $this->assertEquals($data, $expected);
511 * Data provider for test_create_contents_libraries_record().
513 * @return array
515 public function create_contents_libraries_record_provider(): array {
516 return [
517 'Create h5p content library with set dependency type' => [
521 'dynamic'
523 (object) array(
524 'h5pid' => '1',
525 'libraryid' => '1',
526 'dependencytype' => 'dynamic',
527 'dropcss' => '0',
528 'weight' => '1'
531 'Create h5p content library with a default dependency type' => [
536 (object) array(
537 'h5pid' => '1',
538 'libraryid' => '1',
539 'dependencytype' => 'preloaded',
540 'dropcss' => '0',
541 'weight' => '1'
548 * Test the behaviour of create_library_dependency_record(). Test whether the contents libraries
549 * are properly saved in the database.
551 * @dataProvider create_library_dependency_record_provider
552 * @param array $librarydependencydata The library dependency data.
553 * @param \stdClass $expected The expected saved data.
555 public function test_create_library_dependency_record(array $librarydependencydata, \stdClass $expected) {
556 global $DB;
558 $this->resetAfterTest();
560 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
562 $contentlibid = call_user_func_array([$generator, 'create_library_dependency_record'], $librarydependencydata);
564 $data = $DB->get_record('h5p_library_dependencies', ['id' => $contentlibid]);
565 unset($data->id);
567 $this->assertEquals($data, $expected);
571 * Data provider for test_create_library_dependency_record().
573 * @return array
575 public function create_library_dependency_record_provider(): array {
576 return [
577 'Create h5p library dependency with set dependency type' => [
581 'dynamic'
583 (object) array(
584 'libraryid' => '1',
585 'requiredlibraryid' => '1',
586 'dependencytype' => 'dynamic'
589 'Create h5p library dependency with default dependency type' => [
594 (object) array(
595 'libraryid' => '1',
596 'requiredlibraryid' => '1',
597 'dependencytype' => 'preloaded'
604 * Test the behaviour of create_content_file(). Test whether a file belonging to a content is created.
606 * @dataProvider create_content_file_provider
607 * @param array $filedata Data from the file to be created.
608 * @param array $expecteddata Data expected.Data from the file to be created.
610 public function test_create_content_file($filedata, $expecteddata): void {
611 $this->resetAfterTest();
613 $generator = self::getDataGenerator()->get_plugin_generator('core_h5p');
615 if ($expecteddata[1] === 'exception') {
616 $this->expectException('coding_exception');
618 call_user_func_array([$generator, 'create_content_file'], $filedata);
620 $systemcontext = \context_system::instance();
621 $filearea = $filedata[1];
622 $filepath = '/'. dirname($filedata[0]). '/';
623 $filename = basename($filedata[0]);
624 $itemid = $expecteddata[0];
626 $fs = new \file_storage();
627 $exists = $fs->file_exists($systemcontext->id, file_storage::COMPONENT, $filearea, $itemid, $filepath,
628 $filename);
629 if ($expecteddata[1] === true) {
630 $this->assertTrue($exists);
631 } else if ($expecteddata[1] === false) {
632 $this->assertFalse($exists);
637 * Data provider for test_create_content_file(). Data from different files to be created.
639 * @return array
641 public function create_content_file_provider(): array {
642 return [
643 'Create file in content with id 4' => [
645 'images/img1.png',
646 'content',
651 true
654 'Create file in the editor' => [
656 'images/img1.png',
657 'editor'
661 true
664 'Create file in content without id' => [
666 'images/img1.png',
667 'content'
671 'exception'