MDL-67795 h5p: move methods from player to helper
[moodle.git] / h5p / tests / api_test.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Testing the H5P API.
19  *
20  * @package    core_h5p
21  * @category   test
22  * @copyright  2020 Sara Arjona <sara@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 declare(strict_types = 1);
28 namespace core_h5p;
30 defined('MOODLE_INTERNAL') || die();
32 /**
33  * Test class covering the H5P API.
34  *
35  * @package    core_h5p
36  * @copyright  2020 Sara Arjona <sara@moodle.com>
37  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class api_testcase extends \advanced_testcase {
41     /**
42      * Test the behaviour of delete_library().
43      *
44      * @dataProvider  delete_library_provider
45      * @param  string $libraryname          Machine name of the library to delete.
46      * @param  int    $expectedh5p          Total of H5P contents expected after deleting the library.
47      * @param  int    $expectedlibraries    Total of H5P libraries expected after deleting the library.
48      * @param  int    $expectedcontents     Total of H5P content_libraries expected after deleting the library.
49      * @param  int    $expecteddependencies Total of H5P library dependencies expected after deleting the library.
50      */
51     public function test_delete_library(string $libraryname, int $expectedh5p, int $expectedlibraries,
52             int $expectedcontents, int $expecteddependencies): void {
53         global $DB;
55         $this->setRunTestInSeparateProcess(true);
56         $this->resetAfterTest();
58         // Generate h5p related data.
59         $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
60         $generator->generate_h5p_data();
61         $generator->create_library_record('H5P.TestingLibrary', 'TestingLibrary', 1, 0);
63         // Check the current content in H5P tables is the expected.
64         $counth5p = $DB->count_records('h5p');
65         $counth5plibraries = $DB->count_records('h5p_libraries');
66         $counth5pcontents = $DB->count_records('h5p_contents_libraries');
67         $counth5pdependencies = $DB->count_records('h5p_library_dependencies');
69         $this->assertSame(1, $counth5p);
70         $this->assertSame(7, $counth5plibraries);
71         $this->assertSame(5, $counth5pcontents);
72         $this->assertSame(7, $counth5pdependencies);
74         // Delete this library.
75         $factory = new factory();
76         $library = $DB->get_record('h5p_libraries', ['machinename' => $libraryname]);
77         if ($library) {
78             api::delete_library($factory, $library);
79         }
81         // Check the expected libraries and content have been removed.
82         $counth5p = $DB->count_records('h5p');
83         $counth5plibraries = $DB->count_records('h5p_libraries');
84         $counth5pcontents = $DB->count_records('h5p_contents_libraries');
85         $counth5pdependencies = $DB->count_records('h5p_library_dependencies');
87         $this->assertSame($expectedh5p, $counth5p);
88         $this->assertSame($expectedlibraries, $counth5plibraries);
89         $this->assertSame($expectedcontents, $counth5pcontents);
90         $this->assertSame($expecteddependencies, $counth5pdependencies);
91     }
93     /**
94      * Data provider for test_delete_library().
95      *
96      * @return array
97      */
98     public function delete_library_provider(): array {
99         return [
100             'Delete MainLibrary' => [
101                 'MainLibrary',
102                 0,
103                 6,
104                 0,
105                 4,
106             ],
107             'Delete Library1' => [
108                 'Library1',
109                 0,
110                 5,
111                 0,
112                 1,
113             ],
114             'Delete Library2' => [
115                 'Library2',
116                 0,
117                 4,
118                 0,
119                 1,
120             ],
121             'Delete Library3' => [
122                 'Library3',
123                 0,
124                 4,
125                 0,
126                 0,
127             ],
128             'Delete Library4' => [
129                 'Library4',
130                 0,
131                 4,
132                 0,
133                 1,
134             ],
135             'Delete Library5' => [
136                 'Library5',
137                 0,
138                 3,
139                 0,
140                 0,
141             ],
142             'Delete a library without dependencies' => [
143                 'H5P.TestingLibrary',
144                 1,
145                 6,
146                 5,
147                 7,
148             ],
149             'Delete unexisting library' => [
150                 'LibraryX',
151                 1,
152                 7,
153                 5,
154                 7,
155             ],
156         ];
157     }
159     /**
160      * Test the behaviour of get_dependent_libraries().
161      *
162      * @dataProvider  get_dependent_libraries_provider
163      * @param  string $libraryname     Machine name of the library to delete.
164      * @param  int    $expectedvalue   Total of H5P required libraries expected.
165      */
166     public function test_get_dependent_libraries(string $libraryname, int $expectedvalue): void {
167         global $DB;
169         $this->resetAfterTest();
171         // Generate h5p related data.
172         $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
173         $generator->generate_h5p_data();
174         $generator->create_library_record('H5P.TestingLibrary', 'TestingLibrary', 1, 0);
176         // Get required libraries.
177         $library = $DB->get_record('h5p_libraries', ['machinename' => $libraryname], 'id');
178         if ($library) {
179             $libraries = api::get_dependent_libraries((int)$library->id);
180         } else {
181             $libraries = [];
182         }
184         $this->assertCount($expectedvalue, $libraries);
185     }
187     /**
188      * Data provider for test_get_dependent_libraries().
189      *
190      * @return array
191      */
192     public function get_dependent_libraries_provider(): array {
193         return [
194             'Main library of a content' => [
195                 'MainLibrary',
196                 0,
197             ],
198             'Library1' => [
199                 'Library1',
200                 1,
201             ],
202             'Library2' => [
203                 'Library2',
204                 2,
205             ],
206             'Library without dependencies' => [
207                 'H5P.TestingLibrary',
208                 0,
209             ],
210             'Unexisting library' => [
211                 'LibraryX',
212                 0,
213             ],
214         ];
215     }
217     /**
218      * Test the behaviour of get_library().
219      *
220      * @dataProvider  get_library_provider
221      * @param  string $libraryname     Machine name of the library to delete.
222      * @param  bool   $emptyexpected   Wether the expected result is empty or not.
223      */
224     public function test_get_library(string $libraryname, bool $emptyexpected): void {
225         global $DB;
227         $this->resetAfterTest();
229         // Generate h5p related data.
230         $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
231         $generator->generate_h5p_data();
232         $generator->create_library_record('H5P.TestingLibrary', 'TestingLibrary', 1, 0);
234         // Get the library identifier.
235         $library = $DB->get_record('h5p_libraries', ['machinename' => $libraryname], 'id');
236         if ($library) {
237             $result = api::get_library((int)$library->id);
238         } else {
239             $result = null;
240         }
242         if ($emptyexpected) {
243             $this->assertEmpty($result);
244         } else {
245             $this->assertEquals($library->id, $result->id);
246             $this->assertEquals($libraryname, $result->machinename);
247         }
249     }
251     /**
252      * Data provider for test_get_library().
253      *
254      * @return array
255      */
256     public function get_library_provider(): array {
257         return [
258             'Main library of a content' => [
259                 'MainLibrary',
260                 false,
261             ],
262             'Library1' => [
263                 'Library1',
264                 false,
265             ],
266             'Library without dependencies' => [
267                 'H5P.TestingLibrary',
268                 false,
269             ],
270             'Unexisting library' => [
271                 'LibraryX',
272                 true,
273             ],
274         ];
275     }
277     /**
278      * Test the behaviour of get_content_from_pluginfile_url().
279      */
280     public function test_get_content_from_pluginfile_url(): void {
281         $this->setRunTestInSeparateProcess(true);
282         $this->resetAfterTest();
283         $factory = new factory();
285         // Create the H5P data.
286         $filename = 'find-the-words.h5p';
287         $path = __DIR__ . '/fixtures/' . $filename;
288         $fakefile = helper::create_fake_stored_file_from_path($path);
289         $config = (object)[
290             'frame' => 1,
291             'export' => 1,
292             'embed' => 0,
293             'copyright' => 0,
294         ];
296         // Get URL for this H5P content file.
297         $syscontext = \context_system::instance();
298         $url = \moodle_url::make_pluginfile_url(
299             $syscontext->id,
300             \core_h5p\file_storage::COMPONENT,
301             'unittest',
302             $fakefile->get_itemid(),
303             '/',
304             $filename
305         );
307         // Scenario 1: Get the H5P for this URL and check there isn't any existing H5P (because it hasn't been saved).
308         list($newfile, $h5p) = api::get_content_from_pluginfile_url($url->out());
309         $this->assertEquals($fakefile->get_pathnamehash(), $newfile->get_pathnamehash());
310         $this->assertEquals($fakefile->get_contenthash(), $newfile->get_contenthash());
311         $this->assertFalse($h5p);
313         // Scenario 2: Save the H5P and check now the H5P is exactly the same as the original one.
314         $h5pid = helper::save_h5p($factory, $fakefile, $config);
315         list($newfile, $h5p) = api::get_content_from_pluginfile_url($url->out());
317         $this->assertEquals($h5pid, $h5p->id);
318         $this->assertEquals($fakefile->get_pathnamehash(), $h5p->pathnamehash);
319         $this->assertEquals($fakefile->get_contenthash(), $h5p->contenthash);
321         // Scenario 3: Get the H5P for an unexisting H5P file.
322         $url = \moodle_url::make_pluginfile_url(
323             $syscontext->id,
324             \core_h5p\file_storage::COMPONENT,
325             'unittest',
326             $fakefile->get_itemid(),
327             '/',
328             'unexisting.h5p'
329         );
330         list($newfile, $h5p) = api::get_content_from_pluginfile_url($url->out());
331         $this->assertFalse($newfile);
332         $this->assertFalse($h5p);
333     }
335     /**
336      * Test the behaviour of create_content_from_pluginfile_url().
337      */
338     public function test_create_content_from_pluginfile_url(): void {
339         global $DB;
341         $this->setRunTestInSeparateProcess(true);
342         $this->resetAfterTest();
343         $factory = new factory();
345         // Create the H5P data.
346         $filename = 'find-the-words.h5p';
347         $path = __DIR__ . '/fixtures/' . $filename;
348         $fakefile = helper::create_fake_stored_file_from_path($path);
349         $config = (object)[
350             'frame' => 1,
351             'export' => 1,
352             'embed' => 0,
353             'copyright' => 0,
354         ];
356         // Get URL for this H5P content file.
357         $syscontext = \context_system::instance();
358         $url = \moodle_url::make_pluginfile_url(
359             $syscontext->id,
360             \core_h5p\file_storage::COMPONENT,
361             'unittest',
362             $fakefile->get_itemid(),
363             '/',
364             $filename
365         );
367         // Scenario 1: Create the H5P from this URL and check the content is exactly the same as the fake file.
368         $messages = new \stdClass();
369         list($newfile, $h5pid) = api::create_content_from_pluginfile_url($url->out(), $config, $factory, $messages);
370         $this->assertNotFalse($h5pid);
371         $h5p = $DB->get_record('h5p', ['id' => $h5pid]);
372         $this->assertEquals($fakefile->get_pathnamehash(), $h5p->pathnamehash);
373         $this->assertEquals($fakefile->get_contenthash(), $h5p->contenthash);
374         $this->assertTrue(empty($messages->error));
375         $this->assertTrue(empty($messages->info));
377         // Scenario 2: Create the H5P for an unexisting H5P file.
378         $url = \moodle_url::make_pluginfile_url(
379             $syscontext->id,
380             \core_h5p\file_storage::COMPONENT,
381             'unittest',
382             $fakefile->get_itemid(),
383             '/',
384             'unexisting.h5p'
385         );
386         list($newfile, $h5p) = api::create_content_from_pluginfile_url($url->out(), $config, $factory, $messages);
387         $this->assertFalse($newfile);
388         $this->assertFalse($h5p);
389         $this->assertTrue(empty($messages->error));
390         $this->assertTrue(empty($messages->info));
391     }
393     /**
394      * Test the behaviour of delete_content_from_pluginfile_url().
395      */
396     public function test_delete_content_from_pluginfile_url(): void {
397         global $DB;
399         $this->setRunTestInSeparateProcess(true);
400         $this->resetAfterTest();
401         $factory = new factory();
403         // Create the H5P data.
404         $filename = 'find-the-words.h5p';
405         $path = __DIR__ . '/fixtures/' . $filename;
406         $fakefile = helper::create_fake_stored_file_from_path($path);
407         $config = (object)[
408             'frame' => 1,
409             'export' => 1,
410             'embed' => 0,
411             'copyright' => 0,
412         ];
414         // Get URL for this H5P content file.
415         $syscontext = \context_system::instance();
416         $url = \moodle_url::make_pluginfile_url(
417             $syscontext->id,
418             \core_h5p\file_storage::COMPONENT,
419             'unittest',
420             $fakefile->get_itemid(),
421             '/',
422             $filename
423         );
425         // Scenario 1: Try to remove the H5P content for an undeployed file.
426         list($newfile, $h5p) = api::get_content_from_pluginfile_url($url->out());
427         $this->assertEquals(0, $DB->count_records('h5p'));
428         api::delete_content_from_pluginfile_url($url->out(), $factory);
429         $this->assertEquals(0, $DB->count_records('h5p'));
431         // Scenario 2: Deploy an H5P from this URL, check it's created, remove it and check it has been removed as expected.
432         $this->assertEquals(0, $DB->count_records('h5p'));
434         $messages = new \stdClass();
435         list($newfile, $h5pid) = api::create_content_from_pluginfile_url($url->out(), $config, $factory, $messages);
436         $this->assertEquals(1, $DB->count_records('h5p'));
438         api::delete_content_from_pluginfile_url($url->out(), $factory);
439         $this->assertEquals(0, $DB->count_records('h5p'));
441         // Scenario 3: Try to remove the H5P for an unexisting H5P URL.
442         $url = \moodle_url::make_pluginfile_url(
443             $syscontext->id,
444             \core_h5p\file_storage::COMPONENT,
445             'unittest',
446             $fakefile->get_itemid(),
447             '/',
448             'unexisting.h5p'
449         );
450         $this->assertEquals(0, $DB->count_records('h5p'));
451         api::delete_content_from_pluginfile_url($url->out(), $factory);
452         $this->assertEquals(0, $DB->count_records('h5p'));
453     }