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