Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400] [Versions 400 and 401] [Versions 400 and 402] [Versions 400 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 declare(strict_types = 1); 18 19 namespace core_h5p; 20 21 use core_h5p\local\library\autoloader; 22 23 /** 24 * Test class covering the H5P helper. 25 * 26 * @package core_h5p 27 * @category test 28 * @copyright 2019 Sara Arjona <sara@moodle.com> 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 * @covers \core_h5p\helper 31 */ 32 class helper_test extends \advanced_testcase { 33 34 /** 35 * Register the H5P autoloader 36 */ 37 protected function setUp(): void { 38 autoloader::register(); 39 } 40 41 /** 42 * Test the behaviour of get_display_options(). 43 * 44 * @dataProvider display_options_provider 45 * @param bool $frame Whether the frame should be displayed or not 46 * @param bool $export Whether the export action button should be displayed or not 47 * @param bool $embed Whether the embed action button should be displayed or not 48 * @param bool $copyright Whether the copyright action button should be displayed or not 49 * @param int $expected The expectation with the displayoptions value 50 */ 51 public function test_display_options(bool $frame, bool $export, bool $embed, bool $copyright, int $expected): void { 52 $this->setRunTestInSeparateProcess(true); 53 $this->resetAfterTest(); 54 55 $factory = new \core_h5p\factory(); 56 $core = $factory->get_core(); 57 $config = (object)[ 58 'frame' => $frame, 59 'export' => $export, 60 'embed' => $embed, 61 'copyright' => $copyright, 62 ]; 63 64 // Test getting display options. 65 $displayoptions = helper::get_display_options($core, $config); 66 $this->assertEquals($expected, $displayoptions); 67 68 // Test decoding display options. 69 $decoded = helper::decode_display_options($core, $expected); 70 $this->assertEquals($decoded->export, $config->export); 71 $this->assertEquals($decoded->embed, $config->embed); 72 $this->assertEquals($decoded->copyright, $config->copyright); 73 } 74 75 /** 76 * Data provider for test_get_display_options(). 77 * 78 * @return array 79 */ 80 public function display_options_provider(): array { 81 return [ 82 'All display options disabled' => [ 83 false, 84 false, 85 false, 86 false, 87 15, 88 ], 89 'All display options enabled' => [ 90 true, 91 true, 92 true, 93 true, 94 0, 95 ], 96 'Frame disabled and the rest enabled' => [ 97 false, 98 true, 99 true, 100 true, 101 0, 102 ], 103 'Only export enabled' => [ 104 false, 105 true, 106 false, 107 false, 108 12, 109 ], 110 'Only embed enabled' => [ 111 false, 112 false, 113 true, 114 false, 115 10, 116 ], 117 'Only copyright enabled' => [ 118 false, 119 false, 120 false, 121 true, 122 6, 123 ], 124 ]; 125 } 126 127 /** 128 * Test the behaviour of save_h5p() when there are some missing libraries in the system. 129 * @runInSeparateProcess 130 */ 131 public function test_save_h5p_missing_libraries(): void { 132 $this->resetAfterTest(); 133 $factory = new \core_h5p\factory(); 134 135 // Create a user. 136 $user = $this->getDataGenerator()->create_user(); 137 $this->setUser($user); 138 139 // This is a valid .H5P file. 140 $path = __DIR__ . '/fixtures/greeting-card.h5p'; 141 $file = helper::create_fake_stored_file_from_path($path, (int)$user->id); 142 $factory->get_framework()->set_file($file); 143 144 $config = (object)[ 145 'frame' => 1, 146 'export' => 1, 147 'embed' => 0, 148 'copyright' => 0, 149 ]; 150 151 // There are some missing libraries in the system, so an error should be returned. 152 $h5pid = helper::save_h5p($factory, $file, $config); 153 $this->assertFalse($h5pid); 154 $errors = $factory->get_framework()->getMessages('error'); 155 $this->assertCount(1, $errors); 156 $error = reset($errors); 157 $this->assertEquals('missing-required-library', $error->code); 158 $this->assertEquals('Missing required library H5P.GreetingCard 1.0', $error->message); 159 } 160 161 /** 162 * Test the behaviour of save_h5p() when the libraries exist in the system. 163 * @runInSeparateProcess 164 */ 165 public function test_save_h5p_existing_libraries(): void { 166 global $DB; 167 168 $this->resetAfterTest(); 169 $factory = new \core_h5p\factory(); 170 171 // Create a user. 172 $user = $this->getDataGenerator()->create_user(); 173 $this->setUser($user); 174 175 // This is a valid .H5P file. 176 $path = __DIR__ . '/fixtures/greeting-card.h5p'; 177 $file = helper::create_fake_stored_file_from_path($path, (int)$user->id); 178 $factory->get_framework()->set_file($file); 179 180 $config = (object)[ 181 'frame' => 1, 182 'export' => 1, 183 'embed' => 0, 184 'copyright' => 0, 185 ]; 186 // The required libraries exist in the system before saving the .h5p file. 187 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); 188 $lib = $generator->create_library_record('H5P.GreetingCard', 'GreetingCard', 1, 0); 189 $h5pid = helper::save_h5p($factory, $file, $config); 190 $this->assertNotEmpty($h5pid); 191 192 // No errors are raised. 193 $errors = $factory->get_framework()->getMessages('error'); 194 $this->assertCount(0, $errors); 195 196 // And the content in the .h5p file has been saved as expected. 197 $h5p = $DB->get_record('h5p', ['id' => $h5pid]); 198 $this->assertEquals($lib->id, $h5p->mainlibraryid); 199 $this->assertEquals(helper::get_display_options($factory->get_core(), $config), $h5p->displayoptions); 200 $this->assertStringContainsString('Hello world!', $h5p->jsoncontent); 201 } 202 203 /** 204 * Test the behaviour of save_h5p() when the .h5p file is invalid. 205 * @runInSeparateProcess 206 */ 207 public function test_save_h5p_invalid_file(): void { 208 $this->resetAfterTest(); 209 $factory = new \core_h5p\factory(); 210 211 // Create a user. 212 $user = $this->getDataGenerator()->create_user(); 213 $this->setUser($user); 214 215 // Prepare an invalid .H5P file. 216 $path = __DIR__ . '/fixtures/h5ptest.zip'; 217 $file = helper::create_fake_stored_file_from_path($path, (int)$user->id); 218 $factory->get_framework()->set_file($file); 219 $config = (object)[ 220 'frame' => 1, 221 'export' => 1, 222 'embed' => 0, 223 'copyright' => 0, 224 ]; 225 226 // When saving an invalid .h5p file, an error should be raised. 227 $h5pid = helper::save_h5p($factory, $file, $config); 228 $this->assertFalse($h5pid); 229 $errors = $factory->get_framework()->getMessages('error'); 230 $this->assertCount(2, $errors); 231 232 $expectederrorcodes = ['invalid-content-folder', 'invalid-h5p-json-file']; 233 foreach ($errors as $error) { 234 $this->assertContains($error->code, $expectederrorcodes); 235 } 236 } 237 238 /** 239 * Test the behaviour of can_deploy_package(). 240 */ 241 public function test_can_deploy_package(): void { 242 $this->resetAfterTest(); 243 $factory = new \core_h5p\factory(); 244 245 // Create a user. 246 $user = $this->getDataGenerator()->create_user(); 247 $admin = get_admin(); 248 249 // Prepare a valid .H5P file. 250 $path = __DIR__ . '/fixtures/greeting-card.h5p'; 251 252 // Files created by users can't be deployed. 253 $file = helper::create_fake_stored_file_from_path($path, (int)$user->id); 254 $factory->get_framework()->set_file($file); 255 $candeploy = helper::can_deploy_package($file); 256 $this->assertFalse($candeploy); 257 258 // Files created by admins can be deployed, even when the current user is not the admin. 259 $this->setUser($user); 260 $file = helper::create_fake_stored_file_from_path($path, (int)$admin->id); 261 $factory->get_framework()->set_file($file); 262 $candeploy = helper::can_deploy_package($file); 263 $this->assertTrue($candeploy); 264 } 265 266 /** 267 * Test the behaviour of can_update_library(). 268 */ 269 public function test_can_update_library(): void { 270 $this->resetAfterTest(); 271 $factory = new \core_h5p\factory(); 272 273 // Create a user. 274 $user = $this->getDataGenerator()->create_user(); 275 $admin = get_admin(); 276 277 // Prepare a valid .H5P file. 278 $path = __DIR__ . '/fixtures/greeting-card.h5p'; 279 280 // Libraries can't be updated when the file has been created by users. 281 $file = helper::create_fake_stored_file_from_path($path, (int)$user->id); 282 $factory->get_framework()->set_file($file); 283 $candeploy = helper::can_update_library($file); 284 $this->assertFalse($candeploy); 285 286 // Libraries can be updated when the file has been created by admin, even when the current user is not the admin. 287 $this->setUser($user); 288 $file = helper::create_fake_stored_file_from_path($path, (int)$admin->id); 289 $factory->get_framework()->set_file($file); 290 $candeploy = helper::can_update_library($file); 291 $this->assertTrue($candeploy); 292 } 293 294 /** 295 * Test the behaviour of get_messages(). 296 */ 297 public function test_get_messages(): void { 298 $this->resetAfterTest(); 299 300 $factory = new \core_h5p\factory(); 301 $messages = new \stdClass(); 302 303 helper::get_messages($messages, $factory); 304 $this->assertTrue(empty($messages->error)); 305 $this->assertTrue(empty($messages->info)); 306 307 // Add an some messages manually and check they are still there. 308 $messages->error['error1'] = 'Testing ERROR message'; 309 $messages->info['info1'] = 'Testing INFO message'; 310 $messages->info['info2'] = 'Testing INFO message'; 311 helper::get_messages($messages, $factory); 312 $this->assertCount(1, $messages->error); 313 $this->assertCount(2, $messages->info); 314 315 // When saving an invalid .h5p file, 6 errors should be raised. 316 $path = __DIR__ . '/fixtures/h5ptest.zip'; 317 $file = helper::create_fake_stored_file_from_path($path); 318 $factory->get_framework()->set_file($file); 319 $config = (object)[ 320 'frame' => 1, 321 'export' => 1, 322 'embed' => 0, 323 'copyright' => 0, 324 ]; 325 $h5pid = helper::save_h5p($factory, $file, $config); 326 $this->assertFalse($h5pid); 327 helper::get_messages($messages, $factory); 328 $this->assertCount(7, $messages->error); 329 $this->assertCount(2, $messages->info); 330 } 331 332 /** 333 * Test the behaviour of get_export_info(). 334 */ 335 public function test_get_export_info(): void { 336 $this->resetAfterTest(); 337 338 $filename = 'guess-the-answer.h5p'; 339 $syscontext = \context_system::instance(); 340 341 $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); 342 $deployedfile = $generator->create_export_file($filename, 343 $syscontext->id, 344 file_storage::COMPONENT, 345 file_storage::EXPORT_FILEAREA); 346 347 // Test scenario 1: Get export information from correct filename. 348 $helperfile = helper::get_export_info($deployedfile['filename']); 349 $this->assertEquals($deployedfile['filename'], $helperfile['filename']); 350 $this->assertEquals($deployedfile['filepath'], $helperfile['filepath']); 351 $this->assertEquals($deployedfile['filesize'], $helperfile['filesize']); 352 $this->assertEquals($deployedfile['timemodified'], $helperfile['timemodified']); 353 $this->assertEquals($deployedfile['fileurl'], $helperfile['fileurl']); 354 355 // Test scenario 2: Get export information from correct filename and url. 356 $url = \moodle_url::make_pluginfile_url( 357 $syscontext->id, 358 file_storage::COMPONENT, 359 'unittest', 360 0, 361 '/', 362 $deployedfile['filename'], 363 false, 364 true 365 ); 366 $helperfile = helper::get_export_info($deployedfile['filename'], $url); 367 $this->assertEquals($url, $helperfile['fileurl']); 368 369 // Test scenario 3: Get export information from correct filename and factory. 370 $factory = new \core_h5p\factory(); 371 $helperfile = helper::get_export_info($deployedfile['filename'], null, $factory); 372 $this->assertEquals($deployedfile['filename'], $helperfile['filename']); 373 $this->assertEquals($deployedfile['filepath'], $helperfile['filepath']); 374 $this->assertEquals($deployedfile['filesize'], $helperfile['filesize']); 375 $this->assertEquals($deployedfile['timemodified'], $helperfile['timemodified']); 376 $this->assertEquals($deployedfile['fileurl'], $helperfile['fileurl']); 377 378 // Test scenario 4: Get export information from wrong filename. 379 $helperfile = helper::get_export_info('nofileexist.h5p', $url); 380 $this->assertNull($helperfile); 381 } 382 383 /** 384 * Test the parse_js_array function with a range of content. 385 * 386 * @dataProvider parse_js_array_provider 387 * @param string $content 388 * @param array $expected 389 */ 390 public function test_parse_js_array(string $content, array $expected): void { 391 $this->assertEquals($expected, helper::parse_js_array($content)); 392 } 393 394 /** 395 * Data provider for test_parse_js_array(). 396 * 397 * @return array 398 */ 399 public function parse_js_array_provider(): array { 400 $lines = [ 401 "{", 402 " missingTranslation: '[Missing translation :key]',", 403 " loading: 'Loading, please wait...',", 404 " selectLibrary: 'Select the library you wish to use for your content.',", 405 "}", 406 ]; 407 $expected = [ 408 'missingTranslation' => '[Missing translation :key]', 409 'loading' => 'Loading, please wait...', 410 'selectLibrary' => 'Select the library you wish to use for your content.', 411 ]; 412 return [ 413 'Strings with \n' => [ 414 implode("\n", $lines), 415 $expected, 416 ], 417 'Strings with \r\n' => [ 418 implode("\r\n", $lines), 419 $expected, 420 ], 421 'Strings with \r' => [ 422 implode("\r", $lines), 423 $expected, 424 ], 425 ]; 426 } 427 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body