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