2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
19 use core_media_manager
;
20 use media_test_plugin
;
22 defined('MOODLE_INTERNAL') ||
die();
23 require_once(__DIR__
. '/fixtures/testable_core_media_player.php');
26 * Test classes for handling embedded media (audio/video).
30 * @copyright 2012 The Open University
31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 class medialib_test
extends \advanced_testcase
{
36 * Pre-test setup. Preserves $CFG.
38 public function setUp(): void
{
41 // Reset $CFG and $SERVER.
42 $this->resetAfterTest();
44 // "Install" a fake plugin for testing.
45 set_config('version', '2016101400', 'media_test');
47 // Consistent initial setup: all players disabled.
48 \core\plugininfo\media
::set_enabled_plugins('');
50 $_SERVER = array('HTTP_USER_AGENT' => '');
51 $this->pretend_to_be_safari();
55 * Sets user agent to Safari.
57 private function pretend_to_be_safari() {
58 // Pretend to be using Safari browser (must support mp4 for tests to work).
59 \core_useragent
::instance(true, 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) ' .
60 'AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1');
64 * Sets user agent to Firefox.
66 private function pretend_to_be_firefox() {
67 // Pretend to be using Firefox browser (must support ogg for tests to work).
68 \core_useragent
::instance(true, 'Mozilla/5.0 (X11; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0 ');
72 * Test for core_media::get_filename.
74 public function test_get_filename() {
75 $manager = core_media_manager
::instance();
77 $this->assertSame('frog.mp4', $manager->get_filename(new \
moodle_url(
78 '/pluginfile.php/312/mod_page/content/7/frog.mp4')));
79 // This should work even though slasharguments is true, because we want
80 // it to support 'legacy' links if somebody toggles the option later.
81 $this->assertSame('frog.mp4', $manager->get_filename(new \
moodle_url(
82 '/pluginfile.php?file=/312/mod_page/content/7/frog.mp4')));
86 * Test for core_media::get_extension.
88 public function test_get_extension() {
89 $manager = core_media_manager
::instance();
91 $this->assertSame('mp4', $manager->get_extension(new \
moodle_url(
92 '/pluginfile.php/312/mod_page/content/7/frog.mp4')));
93 $this->assertSame('', $manager->get_extension(new \
moodle_url(
94 '/pluginfile.php/312/mod_page/content/7/frog')));
95 $this->assertSame('mp4', $manager->get_extension(new \
moodle_url(
96 '/pluginfile.php?file=/312/mod_page/content/7/frog.mp4')));
97 $this->assertSame('', $manager->get_extension(new \
moodle_url(
98 '/pluginfile.php?file=/312/mod_page/content/7/frog')));
102 * Test for the core_media_player list_supported_urls.
104 public function test_list_supported_urls() {
105 $test = new media_test_plugin(1, 13, ['tst', 'test']);
107 // Some example URLs.
108 $supported1 = new \
moodle_url('http://example.org/1.test');
109 $supported2 = new \
moodle_url('http://example.org/2.TST');
110 $unsupported = new \
moodle_url('http://example.org/2.jpg');
113 $result = $test->list_supported_urls(array());
114 $this->assertEquals(array(), $result);
116 // One supported URL => same.
117 $result = $test->list_supported_urls(array($supported1));
118 $this->assertEquals(array($supported1), $result);
120 // Two supported URLS => same.
121 $result = $test->list_supported_urls(array($supported1, $supported2));
122 $this->assertEquals(array($supported1, $supported2), $result);
124 // One unsupported => none.
125 $result = $test->list_supported_urls(array($unsupported));
126 $this->assertEquals(array(), $result);
128 // Two supported and one unsupported => same.
129 $result = $test->list_supported_urls(array($supported2, $unsupported, $supported1));
130 $this->assertEquals(array($supported2, $supported1), $result);
134 * Test for get_players
136 public function test_get_players() {
137 // All players are initially disabled (except link, which you can't).
138 $manager = core_media_manager
::instance();
139 $this->assertEmpty($this->get_players_test($manager));
141 // A couple enabled, check the order.
142 \core\plugininfo\media
::set_enabled_plugins('youtube,html5audio');
143 $manager = core_media_manager
::instance();
144 $this->assertSame('youtube, html5audio', $this->get_players_test($manager));
146 // Test SWF and HTML5 media order.
147 \core\plugininfo\media
::set_enabled_plugins('html5video,html5audio,swf');
148 $manager = core_media_manager
::instance();
149 $this->assertSame('html5video, html5audio, swf', $this->get_players_test($manager));
151 // Make sure that our test plugin is considered installed.
152 \core\plugininfo\media
::set_enabled_plugins('test,html5video');
153 $manager = core_media_manager
::instance();
154 $this->assertSame('test, html5video', $this->get_players_test($manager));
156 // Make sure that non-existing plugin is NOT considered installed.
157 \core\plugininfo\media
::set_enabled_plugins('nonexistingplugin,html5video');
158 $manager = core_media_manager
::instance();
159 $this->assertSame('html5video', $this->get_players_test($manager));
163 * Test for can_embed_url
165 public function test_can_embed_url() {
166 // All players are initially disabled, so mp4 cannot be rendered.
167 $url = new \
moodle_url('http://example.org/test.mp4');
168 $manager = core_media_manager
::instance();
169 $this->assertFalse($manager->can_embed_url($url));
171 // Enable VideoJS player.
172 \core\plugininfo\media
::set_enabled_plugins('videojs');
173 $manager = core_media_manager
::instance();
174 $this->assertTrue($manager->can_embed_url($url));
177 \core\plugininfo\media
::set_enabled_plugins('videojs,html5video');
178 $manager = core_media_manager
::instance();
179 $this->assertTrue($manager->can_embed_url($url));
182 \core\plugininfo\media
::set_enabled_plugins('html5video');
183 $manager = core_media_manager
::instance();
184 $this->assertTrue($manager->can_embed_url($url));
187 \core\plugininfo\media
::set_enabled_plugins('swf');
188 $manager = core_media_manager
::instance();
189 $this->assertFalse($manager->can_embed_url($url));
193 * Test for embed_url.
194 * Checks multiple format/fallback support.
196 public function test_embed_url_fallbacks() {
198 // Key strings in the embed code that identify with the media formats being tested.
200 $html5video = '</video>';
201 $html5audio = '</audio>';
202 $link = 'mediafallbacklink';
203 $test = 'mediaplugin_test';
205 $url = new \
moodle_url('http://example.org/test.mp4');
207 // All plugins disabled, NOLINK option.
208 \core\plugininfo\media
::set_enabled_plugins('');
209 $manager = core_media_manager
::instance();
210 $t = $manager->embed_url($url, 0, 0, '',
211 array(core_media_manager
::OPTION_NO_LINK
=> true));
213 $this->assertSame('', $t);
215 // All plugins disabled but not NOLINK.
216 \core\plugininfo\media
::set_enabled_plugins('');
217 $manager = core_media_manager
::instance();
218 $t = $manager->embed_url($url);
219 $this->assertStringContainsString($link, $t);
221 // Enable media players that can play the same media formats. (ie. test & html5audio for mp3 files, etc.)
222 \core\plugininfo\media
::set_enabled_plugins('test,html5video,html5audio,swf');
223 $manager = core_media_manager
::instance();
225 // Test media formats that can be played by 2 or more players.
226 $mediaformats = array('mp3', 'mp4');
228 foreach ($mediaformats as $format) {
229 $url = new \
moodle_url('http://example.org/test.' . $format);
230 $textwithlink = $manager->embed_url($url);
231 $textwithoutlink = $manager->embed_url($url, 0, 0, '', array(core_media_manager
::OPTION_NO_LINK
=> true));
235 $this->assertStringContainsString($test, $textwithlink);
236 $this->assertStringNotContainsString($html5video, $textwithlink);
237 $this->assertStringContainsString($html5audio, $textwithlink);
238 $this->assertStringNotContainsString($swf, $textwithlink);
239 $this->assertStringContainsString($link, $textwithlink);
241 $this->assertStringContainsString($test, $textwithoutlink);
242 $this->assertStringNotContainsString($html5video, $textwithoutlink);
243 $this->assertStringContainsString($html5audio, $textwithoutlink);
244 $this->assertStringNotContainsString($swf, $textwithoutlink);
245 $this->assertStringNotContainsString($link, $textwithoutlink);
249 $this->assertStringContainsString($test, $textwithlink);
250 $this->assertStringContainsString($html5video, $textwithlink);
251 $this->assertStringNotContainsString($html5audio, $textwithlink);
252 $this->assertStringNotContainsString($swf, $textwithlink);
253 $this->assertStringContainsString($link, $textwithlink);
255 $this->assertStringContainsString($test, $textwithoutlink);
256 $this->assertStringContainsString($html5video, $textwithoutlink);
257 $this->assertStringNotContainsString($html5audio, $textwithoutlink);
258 $this->assertStringNotContainsString($swf, $textwithoutlink);
259 $this->assertStringNotContainsString($link, $textwithoutlink);
269 * Test for embed_url.
270 * Check SWF works including the special option required to enable it
272 public function test_embed_url_swf() {
273 \core\plugininfo\media
::set_enabled_plugins('swf');
274 $manager = core_media_manager
::instance();
276 // Without any options...
277 $url = new \
moodle_url('http://example.org/test.swf');
278 $t = $manager->embed_url($url);
279 $this->assertStringNotContainsString('</object>', $t);
281 // ...and with the 'no it's safe, I checked it' option.
282 $url = new \
moodle_url('http://example.org/test.swf');
283 $t = $manager->embed_url($url, '', 0, 0, array(core_media_manager
::OPTION_TRUSTED
=> true));
284 $this->assertStringContainsString('</object>', $t);
288 * Same as test_embed_url MP3 test, but for slash arguments.
290 public function test_slash_arguments() {
292 // Again we do not turn slasharguments actually on, because it has to
293 // work regardless of the setting of that variable in case of handling
294 // links created using previous setting.
297 \core\plugininfo\media
::set_enabled_plugins('html5audio');
298 $manager = core_media_manager
::instance();
301 $url = new \
moodle_url('http://example.org/pluginfile.php?file=x/y/z/test.mp3');
302 $t = $manager->embed_url($url);
303 $this->assertStringContainsString('</audio>', $t);
307 * Test for embed_url.
308 * Checks the EMBED_OR_BLANK option.
310 public function test_embed_or_blank() {
311 \core\plugininfo\media
::set_enabled_plugins('html5audio');
312 $manager = core_media_manager
::instance();
313 $this->pretend_to_be_firefox();
315 $options = array(core_media_manager
::OPTION_FALLBACK_TO_BLANK
=> true);
317 // Embed that does match something should still include the link too.
318 $url = new \
moodle_url('http://example.org/test.ogg');
319 $t = $manager->embed_url($url, '', 0, 0, $options);
320 $this->assertStringContainsString('</audio>', $t);
321 $this->assertStringContainsString('mediafallbacklink', $t);
323 // Embed that doesn't match something should be totally blank.
324 $url = new \
moodle_url('http://example.org/test.mp4');
325 $t = $manager->embed_url($url, '', 0, 0, $options);
326 $this->assertSame('', $t);
330 * Test for embed_url.
331 * Checks that size is passed through correctly to player objects and tests
332 * size support in html5video output.
334 public function test_embed_url_size() {
337 // Technically this could break in every format and they handle size
338 // in several different ways, but I'm too lazy to test it in every
339 // format, so let's just pick one to check the values get passed
341 \core\plugininfo\media
::set_enabled_plugins('html5video');
342 $manager = core_media_manager
::instance();
343 $url = new \
moodle_url('http://example.org/test.mp4');
345 // HTML5 default size - specifies core width and does not specify height.
346 $t = $manager->embed_url($url);
347 $this->assertStringContainsString('width="' . $CFG->media_default_width
. '"', $t);
348 $this->assertStringNotContainsString('height', $t);
350 // HTML5 specified size - specifies both.
351 $t = $manager->embed_url($url, '', '666', '101');
352 $this->assertStringContainsString('width="666"', $t);
353 $this->assertStringContainsString('height="101"', $t);
355 // HTML5 size specified in url, overrides call.
356 $url = new \
moodle_url('http://example.org/test.mp4?d=123x456');
357 $t = $manager->embed_url($url, '', '666', '101');
358 $this->assertStringContainsString('width="123"', $t);
359 $this->assertStringContainsString('height="456"', $t);
363 * Test for embed_url.
364 * Checks that name is passed through correctly to player objects and tests
365 * name support in html5video output.
367 public function test_embed_url_name() {
368 // As for size this could break in every format but I'm only testing
370 \core\plugininfo\media
::set_enabled_plugins('html5video');
371 $manager = core_media_manager
::instance();
372 $url = new \
moodle_url('http://example.org/test.mp4');
374 // HTML5 default name - use filename.
375 $t = $manager->embed_url($url);
376 $this->assertStringContainsString('title="test.mp4"', $t);
378 // HTML5 specified name - check escaping.
379 $t = $manager->embed_url($url, 'frog & toad');
380 $this->assertStringContainsString('title="frog & toad"', $t);
384 * Test for split_alternatives.
386 public function test_split_alternatives() {
387 $mediamanager = core_media_manager
::instance();
389 // Single URL - identical moodle_url.
390 $mp4 = 'http://example.org/test.mp4';
391 $result = $mediamanager->split_alternatives($mp4, $w, $h);
392 $this->assertEquals($mp4, $result[0]->out(false));
394 // Width and height weren't specified.
395 $this->assertEquals(0, $w);
396 $this->assertEquals(0, $h);
398 // Two URLs - identical moodle_urls.
399 $webm = 'http://example.org/test.webm';
400 $result = $mediamanager->split_alternatives("$mp4#$webm", $w, $h);
401 $this->assertEquals($mp4, $result[0]->out(false));
402 $this->assertEquals($webm, $result[1]->out(false));
404 // Two URLs plus dimensions.
406 $result = $mediamanager->split_alternatives("$mp4#$webm#$size", $w, $h);
407 $this->assertEquals($mp4, $result[0]->out(false));
408 $this->assertEquals($webm, $result[1]->out(false));
409 $this->assertEquals(400, $w);
410 $this->assertEquals(280, $h);
412 // Two URLs plus legacy dimensions (use last one).
413 $result = $mediamanager->split_alternatives("$mp4?d=1x1#$webm?$size", $w, $h);
414 $this->assertEquals($mp4, $result[0]->out(false));
415 $this->assertEquals($webm, $result[1]->out(false));
416 $this->assertEquals(400, $w);
417 $this->assertEquals(280, $h);
421 * Test for embed_alternatives (with multiple urls)
423 public function test_embed_alternatives() {
424 // Most aspects of this are same as single player so let's just try
425 // a single typical / complicated scenario.
427 // MP4, OGV, WebM and FLV.
429 new \
moodle_url('http://example.org/test.mp4'),
430 new \
moodle_url('http://example.org/test.ogv'),
431 new \
moodle_url('http://example.org/test.webm'),
432 new \
moodle_url('http://example.org/test.flv'),
435 // Enable html5 and "test" ("test" first).
436 \core\plugininfo\media
::set_enabled_plugins('test,html5video');
437 $manager = core_media_manager
::instance();
439 // Result should contain HTML5 with two sources + FLV.
440 $t = $manager->embed_alternatives($urls);
442 // HTML5 sources - mp4, but not ogv, flv or webm (not supported in Safari).
443 $this->assertStringContainsString('<source src="http://example.org/test.mp4"', $t);
444 $this->assertStringNotContainsString('<source src="http://example.org/test.ogv"', $t);
445 $this->assertStringNotContainsString('<source src="http://example.org/test.webm"', $t);
446 $this->assertStringNotContainsString('<source src="http://example.org/test.flv"', $t);
448 // FLV is before the video tag (indicating html5 is used as fallback to flv
449 // and not vice versa).
450 $this->assertTrue((bool)preg_match('~mediaplugin_test.*<video~s', $t));
452 // Do same test with firefox and check we get the webm and not mp4.
453 $this->pretend_to_be_firefox();
454 $t = $manager->embed_alternatives($urls);
456 // HTML5 sources - mp4, ogv and webm, but not flv.
457 $this->assertStringContainsString('<source src="http://example.org/test.mp4"', $t);
458 $this->assertStringContainsString('<source src="http://example.org/test.ogv"', $t);
459 $this->assertStringContainsString('<source src="http://example.org/test.webm"', $t);
460 $this->assertStringNotContainsString('<source src="http://example.org/test.flv"', $t);
464 * Make sure the instance() method returns singleton for the same page and different object for another page
466 public function test_initialise() {
467 $moodlepage1 = new \
moodle_page();
469 $mediamanager1 = core_media_manager
::instance($moodlepage1);
470 $mediamanager2 = core_media_manager
::instance($moodlepage1);
472 $this->assertSame($mediamanager1, $mediamanager2);
474 $moodlepage3 = new \
moodle_page();
475 $mediamanager3 = core_media_manager
::instance($moodlepage3);
477 $this->assertNotSame($mediamanager1, $mediamanager3);
482 * Access list of players as string, shortening it by getting rid of
484 * @param core_media_manager $manager The core_media_manager instance
485 * @return string Comma-separated list of players
487 public function get_players_test($manager) {
488 $method = new \
ReflectionMethod("core_media_manager", "get_players");
489 $method->setAccessible(true);
490 $players = $method->invoke($manager);
492 foreach ($players as $player) {
496 $out .= str_replace('core_media_player_', '', preg_replace('/^media_(.*)_plugin$/', '$1', get_class($player)));