Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310] [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 Moodle local class for managing the H5P Editor.
  19   *
  20   * @package    core_h5p
  21   * @category   test
  22   * @copyright  2020 Victor Deniz <victor@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace core_h5p;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  use advanced_testcase;
  31  use core_h5p\local\library\autoloader;
  32  use MoodleQuickForm;
  33  use page_requirements_manager;
  34  
  35  /**
  36   *
  37   * Test class covering the editor class.
  38   *
  39   * @package    core_h5p
  40   * @copyright  2020 Victor Deniz <victor@moodle.com>
  41   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   *
  43   * @runTestsInSeparateProcesses
  44   */
  45  class editor_testcase extends advanced_testcase {
  46  
  47      /**
  48       * Form object to be used in test case.
  49       */
  50      protected function get_test_form() {
  51          global $CFG;
  52  
  53          require_once($CFG->libdir . '/formslib.php');
  54  
  55          return new class extends \moodleform {
  56              /**
  57               * Form definition.
  58               */
  59              public function definition(): void {
  60                  // No definition required.
  61              }
  62  
  63              /**
  64               * Returns form reference.
  65               *
  66               * @return MoodleQuickForm
  67               */
  68              public function getform() {
  69                  $mform = $this->_form;
  70                  return $mform;
  71              }
  72          };
  73      }
  74  
  75      /**
  76       * Test that existing content is properly set.
  77       */
  78      public function test_set_content() {
  79          $this->resetAfterTest();
  80  
  81          autoloader::register();
  82  
  83          // Add H5P content.
  84          // This is a valid .H5P file.
  85          $filename = 'find-the-words.h5p';
  86          $path = __DIR__ . '/fixtures/' . $filename;
  87          $syscontext = \context_system::instance();
  88          $filerecord = [
  89              'contextid' => $syscontext->id,
  90              'component' => \core_h5p\file_storage::COMPONENT,
  91              'filearea' => 'unittest',
  92              'itemid' => 0,
  93              'filepath' => '/',
  94              'filename' => $filename,
  95          ];
  96          // Load the h5p file into DB.
  97          $fs = get_file_storage();
  98          $file = $fs->create_file_from_pathname($filerecord, $path);
  99          // Make the URL to pass to the WS.
 100          $url = \moodle_url::make_pluginfile_url(
 101              $syscontext->id,
 102              \core_h5p\file_storage::COMPONENT,
 103              'unittest',
 104              0,
 105              '/',
 106              $filename
 107          );
 108          $config = new \stdClass();
 109  
 110          $h5pplayer = new player($url->out(), $config);
 111  
 112          // Call the method. We need the id of the new H5P content.
 113          $rc = new \ReflectionClass(player::class);
 114          $rcp = $rc->getProperty('h5pid');
 115          $rcp->setAccessible(true);
 116          $h5pid = $rcp->getValue($h5pplayer);
 117  
 118          $editor = new editor();
 119          $editor->set_content($h5pid);
 120  
 121          // Check we get the H5P content.
 122          $rc = new \ReflectionClass(editor::class);
 123          $rcp = $rc->getProperty('oldcontent');
 124          $rcp->setAccessible(true);
 125          $oldcontent = $rcp->getValue($editor);
 126  
 127          $core = (new factory)->get_core();
 128          $this->assertSame($core->loadContent($h5pid), $oldcontent);
 129  
 130          // Check we get the file of the H5P content.
 131          $rcp = $rc->getProperty('oldfile');
 132          $rcp->setAccessible(true);
 133          $oldfile = $rcp->getValue($editor);
 134  
 135          $this->assertSame($file->get_contenthash(), $oldfile->get_contenthash());
 136      }
 137  
 138      /**
 139       * Tests that library and file area are properly set.
 140       */
 141      public function test_set_library() {
 142          global $USER;
 143  
 144          $library = 'H5P.Accordion 1.5';
 145          $contextid = 1;
 146          $filearea = 'unittest';
 147          $filename = 'export.h5p';
 148  
 149          // Call method.
 150          $editor = new editor();
 151          $editor->set_library($library, $contextid, file_storage::COMPONENT, $filearea, 0, '/', $filename);
 152  
 153          // Check that the library has the right value.
 154          $rc = new \ReflectionClass(editor::class);
 155          $rcp = $rc->getProperty('library');
 156          $rcp->setAccessible(true);
 157          $actual = $rcp->getValue($editor);
 158  
 159          $this->assertSame($library, $actual);
 160  
 161          // Check that the file area has the right value.
 162          $expected = [
 163              'contextid' => $contextid,
 164              'component' => file_storage::COMPONENT,
 165              'filearea' => $filearea,
 166              'itemid' => 0,
 167              'filepath' => '/',
 168              'filename' => $filename,
 169              'userid' => $USER->id
 170          ];
 171  
 172          $rcp = $rc->getProperty('filearea');
 173          $rcp->setAccessible(true);
 174          $actual = $rcp->getValue($editor);
 175  
 176          $this->assertEquals($expected, $actual);
 177      }
 178  
 179      /**
 180       * Test that required assets (js and css) and form will be loaded in page.
 181       */
 182      public function test_add_editor_to_form() {
 183          global $PAGE, $CFG;
 184  
 185          $this->resetAfterTest();
 186          $this->setAdminUser();
 187  
 188          // Get form data.
 189          $form = $this->get_test_form();
 190          $mform = $form->getform();
 191  
 192          // Call method.
 193          $editor = new editor();
 194          $editor->add_editor_to_form($mform);
 195  
 196          // Check $PAGE has the expected css and js scripts.
 197          $rc = new \ReflectionClass(page_requirements_manager::class);
 198          $rcp = $rc->getProperty('cssurls');
 199          $rcp2 = $rc->getProperty('jsincludes');
 200          $rcp->setAccessible(true);
 201          $rcp2->setAccessible(true);
 202          $actualcss = array_keys($rcp->getValue($PAGE->requires));
 203          $actualjs = array_keys($rcp2->getValue($PAGE->requires)['head']);
 204          $cachebuster = helper::get_cache_buster();
 205  
 206          $h5pcorepath = autoloader::get_h5p_core_library_url()->out();
 207  
 208          $expectedcss = \H5PCore::$styles;
 209          $expectedjs = \H5PCore::$scripts;
 210  
 211          array_walk($expectedcss, function(&$item, $key) use ($h5pcorepath, $cachebuster) {
 212              $item = $h5pcorepath . $item. $cachebuster;
 213  
 214          });
 215  
 216          array_walk($expectedjs, function(&$item, $key) use ($h5pcorepath, $cachebuster) {
 217              $item = $h5pcorepath . $item . $cachebuster;
 218          });
 219  
 220          $expectedjs[] = (new \moodle_url('/h5p/js/h5p_overrides.js' . $cachebuster))->out();
 221          $expectedjs[] = autoloader::get_h5p_editor_library_url('scripts/h5peditor-editor.js' . $cachebuster)->out();
 222          $expectedjs[] = autoloader::get_h5p_editor_library_url('scripts/h5peditor-init.js' . $cachebuster)->out();
 223  
 224          // Sort arrays before comparison.
 225          sort($actualcss);
 226          sort($actualjs);
 227          sort($expectedcss);
 228          sort($expectedjs);
 229  
 230          $this->assertSame($expectedcss, $actualcss);
 231          $this->assertSame($expectedjs, $actualjs);
 232  
 233          // H5P Editor expected form fields.
 234          $this->assertTrue($mform->elementExists('h5pparams'));
 235          $this->assertTrue($mform->elementExists('h5plibrary'));
 236          $this->assertTrue($mform->elementExists('h5paction'));
 237      }
 238  
 239      /**
 240       * Test new content creation.
 241       */
 242      public function test_save_content() {
 243          global $DB;
 244  
 245          $this->resetAfterTest();
 246  
 247          // Fake form data sent during creation.
 248          $data = new \stdClass();
 249          $data->h5plibrary = "H5P.ArithmeticQuiz 1.1";
 250          $data->h5pparams = '{"params":{"quizType":"arithmetic","arithmeticType":"addition","UI":{"score":"Score:","time":"Time: @time"},
 251                  "intro":"This is a content for testing"},"metadata":{"defaultLanguage":"en","title":"Testing content"}}';
 252  
 253          $title = 'libtest';
 254          $library = 'H5P.ArithmeticQuiz 1.1';
 255          $machinename = 'H5P.ArithmeticQuiz';
 256          $contextid = 1;
 257          $filearea = 'unittest';
 258          $filename = 'export.h5p';
 259  
 260          // Fake installed library for the H5P content.
 261          $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
 262  
 263          $semantics = json_encode([['type' => 'text', 'name' => 'text', 'label' => 'Plain text', 'description' => 'Some text']]);
 264          $generator->create_library_record($machinename, $title, 1, 1, 2, $semantics);
 265  
 266          $editor = new editor();
 267          $editor->set_library($library, $contextid, file_storage::COMPONENT, $filearea, 0, '/', $filename);
 268          $newcontentid = $editor->save_content($data);
 269  
 270          // Check the H5P content file was created where expected.
 271          $fs = get_file_storage();
 272          $out = $fs->get_file($contextid, file_storage::COMPONENT, $filearea, 0, '/', $filename);
 273          $this->assertNotEmpty($out);
 274      }
 275  }