Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 39 and 401]

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