See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
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/>. 16 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 */ 25 26 declare(strict_types = 1); 27 28 namespace core_h5p; 29 30 defined('MOODLE_INTERNAL') || die(); 31 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 { 40 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; 54 55 $this->setRunTestInSeparateProcess(true); 56 $this->resetAfterTest(); 57 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); 62 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'); 68 69 $this->assertSame(1, $counth5p); 70 $this->assertSame(7, $counth5plibraries); 71 $this->assertSame(5, $counth5pcontents); 72 $this->assertSame(7, $counth5pdependencies); 73 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 } 80 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'); 86 87 $this->assertSame($expectedh5p, $counth5p); 88 $this->assertSame($expectedlibraries, $counth5plibraries); 89 $this->assertSame($expectedcontents, $counth5pcontents); 90 $this->assertSame($expecteddependencies, $counth5pdependencies); 91 } 92 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 } 158 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; 168 169 $this->resetAfterTest(); 170 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); 175 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 } 183 184 $this->assertCount($expectedvalue, $libraries); 185 } 186 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 } 216 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; 226 227 $this->resetAfterTest(); 228 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); 233 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 } 241 242 if ($emptyexpected) { 243 $this->assertEmpty($result); 244 } else { 245 $this->assertEquals($library->id, $result->id); 246 $this->assertEquals($libraryname, $result->machinename); 247 } 248 249 } 250 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 } 276 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(); 284 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 ]; 295 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 ); 306 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); 312 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()); 316 317 $this->assertEquals($h5pid, $h5p->id); 318 $this->assertEquals($fakefile->get_pathnamehash(), $h5p->pathnamehash); 319 $this->assertEquals($fakefile->get_contenthash(), $h5p->contenthash); 320 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 } 334 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; 340 341 $this->setRunTestInSeparateProcess(true); 342 $this->resetAfterTest(); 343 $factory = new factory(); 344 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 ]; 355 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 ); 366 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)); 376 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 } 392 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; 398 399 $this->setRunTestInSeparateProcess(true); 400 $this->resetAfterTest(); 401 $factory = new factory(); 402 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 ]; 413 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 ); 424 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')); 430 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')); 433 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')); 437 438 api::delete_content_from_pluginfile_url($url->out(), $factory); 439 $this->assertEquals(0, $DB->count_records('h5p')); 440 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 } 454 455 /** 456 * Test the behaviour of get_export_info_from_context_id(). 457 */ 458 public function test_get_export_info_from_context_id(): void { 459 global $DB; 460 461 $this->setRunTestInSeparateProcess(true); 462 $this->resetAfterTest(); 463 $factory = new factory(); 464 465 // Create the H5P data. 466 $filename = 'find-the-words.h5p'; 467 $syscontext = \context_system::instance(); 468 469 // Test scenario 1: H5P exists and deployed. 470 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); 471 $fakeexportfile = $generator->create_export_file($filename, 472 $syscontext->id, 473 \core_h5p\file_storage::COMPONENT, 474 \core_h5p\file_storage::EXPORT_FILEAREA); 475 476 $exportfile = api::get_export_info_from_context_id($syscontext->id, 477 $factory, 478 \core_h5p\file_storage::COMPONENT, 479 \core_h5p\file_storage::EXPORT_FILEAREA); 480 $this->assertEquals($fakeexportfile['filename'], $exportfile['filename']); 481 $this->assertEquals($fakeexportfile['filepath'], $exportfile['filepath']); 482 $this->assertEquals($fakeexportfile['filesize'], $exportfile['filesize']); 483 $this->assertEquals($fakeexportfile['timemodified'], $exportfile['timemodified']); 484 $this->assertEquals($fakeexportfile['fileurl'], $exportfile['fileurl']); 485 486 // Test scenario 2: H5P exist, deployed but the content has changed. 487 // We need to change the contenthash to simulate the H5P file was changed. 488 $h5pfile = $DB->get_record('h5p', []); 489 $h5pfile->contenthash = sha1('testedit'); 490 $DB->update_record('h5p', $h5pfile); 491 $exportfile = api::get_export_info_from_context_id($syscontext->id, 492 $factory, 493 \core_h5p\file_storage::COMPONENT, 494 \core_h5p\file_storage::EXPORT_FILEAREA); 495 $this->assertNull($exportfile); 496 497 // Tests scenario 3: H5P is not deployed. 498 // We need to delete the H5P record to simulate the H5P was not deployed. 499 $DB->delete_records('h5p', ['id' => $h5pfile->id]); 500 $exportfile = api::get_export_info_from_context_id($syscontext->id, 501 $factory, 502 \core_h5p\file_storage::COMPONENT, 503 \core_h5p\file_storage::EXPORT_FILEAREA); 504 $this->assertNull($exportfile); 505 } 506 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body