2fd0d5b0e9d95a77d259adbfd5fdcf2de3752168
[moodle.git] / lib / simpletest / testoutputlib.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
19 /**
20  * Unit tests for (some of) ../outputlib.php.
21  *
22  * @package   moodlecore
23  * @copyright 2009 Tim Hunt
24  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later (5)
25  */
27 if (!defined('MOODLE_INTERNAL')) {
28     die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
29 }
30 require_once($CFG->libdir . '/outputlib.php');
32 //TODO: MDL-21361
33 return;
35 $e = <<<EOT
37 /**
38  * Subclass of renderer_factory_base for testing. Implement abstract method and
39  * count calls, so we can test caching behaviour.
40  *
41  * @copyright 2009 Tim Hunt
42  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43  */
44 class testable_renderer_factory extends renderer_factory_base {
45     public $createcalls = array();
47     public function __construct() {
48         parent::__construct(null);
49     }
51     public function get_renderer($module, $page, $subtype=null) {
52         if (!in_array(array($module, $subtype), $this->createcalls)) {
53             $this->createcalls[] = array($module, $subtype);
54         }
55         return new core_renderer($page);
56     }
58     public function standard_renderer_class_for_plugin($module, $subtype=null) {
59         return parent::standard_renderer_class_for_plugin($module, $subtype);
60     }
61 }
64 /**
65  * Renderer class for testing.
66  *
67  * @copyright 2009 Tim Hunt
68  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
69  */
70 class mod_test_renderer extends core_renderer {
71     public function __construct($containerstack, $page) {
72         parent::__construct($containerstack, $page, null);
73     }
75     public function greeting($name = 'world') {
76         return '<h1>Hello ' . $name . '!</h1>';
77     }
79     public function box($content, $id = '') {
80         return box_start($id) . $content . box_end();
81     }
83     public function box_start($id = '') {
84         if ($id) {
85             $id = ' id="' . $id . '"';
86         }
87         $this->containerstack->push('box', '</div>');
88         return '<div' . $id . '>';
89     }
91     public function box_end() {
92         return $this->containerstack->pop('box');
93     }
94 }
97 /**
98  * Renderer class for testing subrendering feature
99  *
100  * @copyright 2009 David Mudrak
101  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
102  */
103 class mod_test_subtype_renderer extends core_renderer {
104     public function __construct($containerstack, $page) {
105         parent::__construct($containerstack, $page, null);
106     }
108     public function signature($user = 'Administrator') {
109         return '<div class="signature">Best regards, ' . $user . '</div>';
110     }
114 /**
115  * Unit tests for the requriement_base base class.
116  *
117  * @copyright 2009 Tim Hunt
118  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
119  */
120 class renderer_factory_base_test extends UnitTestCase {
122     public static $includecoverage = array('lib/outputlib.php');
124     public function test_get_calls_create() {
125         // Set up.
126         $factory = new testable_renderer_factory();
127         // Exercise SUT.
128         $renderer    = $factory->get_renderer('modulename', new moodle_page);
129         $subrenderer = $factory->get_renderer('modulename', new moodle_page, 'subtype');
130         $cached      = $factory->get_renderer('modulename', new moodle_page);
131         // Verify outcome
132         $this->assertEqual(array(array('modulename', null), array('modulename', 'subtype')), $factory->createcalls);
134     }
136     public function test_standard_renderer_class_for_plugin_core() {
137         // Set up.
138         $factory = new testable_renderer_factory();
139         // Exercise SUT.
140         $classname = $factory->standard_renderer_class_for_plugin('core');
141         // Verify outcome
142         $this->assertEqual('core_renderer', $classname);
143     }
145     public function test_standard_renderer_class_for_plugin_test() {
146         // Set up.
147         $factory = new testable_renderer_factory();
148         // Exercise SUT.
149         $classname = $factory->standard_renderer_class_for_plugin('mod_test');
150         // Verify outcome
151         $this->assertEqual('mod_test_renderer', $classname);
152     }
154     public function test_standard_renderer_class_for_plugin_test_with_subtype() {
155         // Set up.
156         $factory = new testable_renderer_factory();
157         // Exercise SUT.
158         $classname = $factory->standard_renderer_class_for_plugin('mod_test', 'subtype');
159         // Verify outcome
160         $this->assertEqual('mod_test_subtype_renderer', $classname);
161     }
163     public function test_standard_renderer_class_for_plugin_unknown() {
164         // Set up.
165         $factory = new testable_renderer_factory();
166         $this->expectException();
167         // Exercise SUT.
168         $classname = $factory->standard_renderer_class_for_plugin('something_that_does_not_exist');
169     }
173 /**
174  * Unit tests for the standard_renderer_factory class.
175  *
176  * @copyright 2009 Tim Hunt
177  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
178  */
179 class standard_renderer_factory_test extends UnitTestCase {
181     public static $includecoverage = array('lib/outputrenderers.php', 'lib/outputcomponents.php');
182     protected $factory;
184     public function setUp() {
185         parent::setUp();
186         $this->factory = new standard_renderer_factory(null, null);
187     }
189     public function tearDown() {
190         $this->factory = null;
191         parent::tearDown();
192     }
194     public function test_get_core_renderer() {
195         $renderer = $this->factory->get_renderer('core', new moodle_page);
196         $this->assertIsA($renderer, 'core_renderer');
197     }
199     public function test_get_test_renderer() {
200         $renderer = $this->factory->get_renderer('mod_test', new moodle_page);
201         $this->assertIsA($renderer, 'mod_test_renderer');
202     }
204     public function test_get_test_subtype_renderer() {
205         $renderer = $this->factory->get_renderer('mod_test', new moodle_page, 'subtype');
206         $this->assertIsA($renderer, 'mod_test_subtype_renderer');
207     }
211 /**
212  * Test-specific subclass that implements a getter for $prefixes.
213  *
214  * @copyright 2009 Tim Hunt
215  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
216  */
217 class testable_theme_overridden_renderer_factory extends theme_overridden_renderer_factory {
219     public static $includecoverage = array('lib/outputlib.php');
220     public function get_prefixes() {
221         return $this->prefixes;
222     }
226 /**
227  * Unit tests for the theme_overridden_renderer_factory class.
228  *
229  * @copyright 2009 Tim Hunt
230  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
231  */
232 /*class theme_overridden_renderer_factory_test extends UnitTestCase { // TODO: MDL-21138 rewrite theme unit tests
234     public static $includecoverage = array('lib/outputlib.php');
235     protected $originalcfgthemedir;
236     protected $workspace;
237     protected $page;
238     protected $foldertocleanup = null;
240     public function setUp() {
241         global $CFG;
242         parent::setUp();
244         $this->originalcfgthemedir = $CFG->themedir;
246         $this->workspace = 'temp/theme_overridden_renderer_factory_fixtures';
247         make_upload_directory($this->workspace);
248         $CFG->themedir = $CFG->dataroot . '/' . $this->workspace;
249         $this->foldertocleanup = $CFG->themedir;
251         $this->page = new stdClass;
252     }
254     public function tearDown() {
255         global $CFG;
256         if (!empty($this->foldertocleanup)) {
257             fulldelete($this->foldertocleanup);
258             $this->foldertocleanup = null;
259         }
260         $CFG->themedir = $this->originalcfgthemedir;
261         parent::tearDown();
262     }
264     protected function make_theme($name) {
265         global $CFG;
266         $theme = new stdClass;
267         $theme->name = $name;
268         $theme->dir = $CFG->themedir . '/' . $name;
269         make_upload_directory($this->workspace . '/' . $name);
270         return $theme;
271     }
273     protected function write_renderers_file($theme, $code) {
274         $filename = $theme->dir . '/lib.php';
275         file_put_contents($filename, "<?php\n" . $code);
276     }
278     public function test_constructor_theme_with_renderes() {
279         // Set up.
280         $theme = $this->make_theme('mytheme');
281         $this->write_renderers_file($theme, '');
283         // Exercise SUT.
284         $factory = new testable_theme_overridden_renderer_factory($theme, $this->page);
286         // Verify outcome
287         $this->assertEqual(array('mytheme_'), $factory->get_prefixes());
288     }
290     public function test_constructor_theme_without_renderes() {
291         // Set up.
292         $theme = $this->make_theme('mytheme');
294         // Exercise SUT.
295         $factory = new testable_theme_overridden_renderer_factory($theme, $this->page);
297         // Verify outcome
298         $this->assertEqual(array(), $factory->get_prefixes());
299     }
301     public function test_constructor_theme_with_parent() {
302         // Set up.
303         $theme = $this->make_theme('mytheme');
304         $theme->parent = 'parenttheme';
305         $parenttheme = $this->make_theme('parenttheme');
306         $this->write_renderers_file($parenttheme, '');
308         // Exercise SUT.
309         $factory = new testable_theme_overridden_renderer_factory($theme, $this->page);
311         // Verify outcome
312         $this->assertEqual(array('parenttheme_'), $factory->get_prefixes());
313     }
315     public function test_get_renderer_not_overridden() {
316         // Set up.
317         $theme = $this->make_theme('mytheme');
318         $this->write_renderers_file($theme, '');
319         $factory = new testable_theme_overridden_renderer_factory($theme, $this->page);
321         // Exercise SUT.
322         $renderer    = $factory->get_renderer('mod_test', new moodle_page);
323         $subrenderer = $factory->get_renderer('mod_test', new moodle_page, 'subtype');
325         // Verify outcome
326         $this->assertIsA($renderer, 'mod_test_renderer');
327         $this->assertIsA($subrenderer, 'mod_test_subtype_renderer');
328     }
330     public function test_get_renderer_overridden() {
331         // Set up - be very careful because the class under test uses require-once. Pick a unique theme name.
332         $theme = $this->make_theme('testrenderertheme');
333         $this->write_renderers_file($theme, '
334         class testrenderertheme_mod_test_renderer extends mod_test_renderer {
335         }');
336         $factory = new testable_theme_overridden_renderer_factory($theme, $this->page);
338         // Exercise SUT.
339         $renderer    = $factory->get_renderer('mod_test', new moodle_page);
340         $subrenderer = $factory->get_renderer('mod_test', new moodle_page, 'subtype');
342         // Verify outcome
343         $this->assertIsA($renderer, 'testrenderertheme_mod_test_renderer');
344         $this->assertIsA($subrenderer, 'mod_test_subtype_renderer');
345     }
347     public function test_get_renderer_overridden_in_parent() {
348         // Set up.
349         $theme = $this->make_theme('childtheme');
350         $theme->parent = 'parentrenderertheme';
351         $parenttheme = $this->make_theme('parentrenderertheme');
352         $this->write_renderers_file($theme, '');
353         $this->write_renderers_file($parenttheme, '
354         class parentrenderertheme_core_renderer extends core_renderer {
355         }');
356         $factory = new testable_theme_overridden_renderer_factory($theme, $this->page);
358         // Exercise SUT.
359         $renderer = $factory->get_renderer('core', new moodle_page);
361         // Verify outcome
362         $this->assertIsA($renderer, 'parentrenderertheme_core_renderer');
363     }
365     public function test_get_renderer_overridden_in_both() {
366         // Set up.
367         $theme = $this->make_theme('ctheme');
368         $theme->parent = 'ptheme';
369         $parenttheme = $this->make_theme('ptheme');
370         $this->write_renderers_file($theme, '
371         class ctheme_core_renderer extends core_renderer {
372         }');
373         $this->write_renderers_file($parenttheme, '
374         class ptheme_core_renderer extends core_renderer {
375         }');
376         $factory = new testable_theme_overridden_renderer_factory($theme, $this->page);
378         // Exercise SUT.
379         $renderer = $factory->get_renderer('core', new moodle_page);
381         // Verify outcome
382         $this->assertIsA($renderer, 'ctheme_core_renderer');
383     }
384 }*/
386 /**
387  * Unit tests for the xhtml_container_stack class.
388  *
389  * These tests assume that developer debug mode is on, which, at the time of
390  * writing, is true. admin/report/unittest/index.php forces it on.
391  *
392  * @copyright 2009 Tim Hunt
393  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
394  */
395 class xhtml_container_stack_test extends UnitTestCase {
397     public static $includecoverage = array('lib/outputlib.php');
398     protected function start_capture() {
399         ob_start();
400     }
402     protected function end_capture() {
403         $result = ob_get_contents();
404         ob_end_clean();
405         return $result;
406     }
408     public function test_push_then_pop() {
409         // Set up.
410         $stack = new xhtml_container_stack();
411         // Exercise SUT.
412         $this->start_capture();
413         $stack->push('testtype', '</div>');
414         $html = $stack->pop('testtype');
415         $errors = $this->end_capture();
416         // Verify outcome
417         $this->assertEqual('</div>', $html);
418         $this->assertEqual('', $errors);
419     }
421     public function test_mismatched_pop_prints_warning() {
422         // Set up.
423         $stack = new xhtml_container_stack();
424         $stack->push('testtype', '</div>');
425         // Exercise SUT.
426         $this->start_capture();
427         $html = $stack->pop('mismatch');
428         $errors = $this->end_capture();
429         // Verify outcome
430         $this->assertEqual('</div>', $html);
431         $this->assertNotEqual('', $errors);
432     }
434     public function test_pop_when_empty_prints_warning() {
435         // Set up.
436         $stack = new xhtml_container_stack();
437         // Exercise SUT.
438         $this->start_capture();
439         $html = $stack->pop('testtype');
440         $errors = $this->end_capture();
441         // Verify outcome
442         $this->assertEqual('', $html);
443         $this->assertNotEqual('', $errors);
444     }
446     public function test_correct_nesting() {
447         // Set up.
448         $stack = new xhtml_container_stack();
449         // Exercise SUT.
450         $this->start_capture();
451         $stack->push('testdiv', '</div>');
452         $stack->push('testp', '</p>');
453         $html2 = $stack->pop('testp');
454         $html1 = $stack->pop('testdiv');
455         $errors = $this->end_capture();
456         // Verify outcome
457         $this->assertEqual('</p>', $html2);
458         $this->assertEqual('</div>', $html1);
459         $this->assertEqual('', $errors);
460     }
462     public function test_pop_all_but_last() {
463         // Set up.
464         $stack = new xhtml_container_stack();
465         $stack->push('test1', '</h1>');
466         $stack->push('test2', '</h2>');
467         $stack->push('test3', '</h3>');
468         // Exercise SUT.
469         $this->start_capture();
470         $html = $stack->pop_all_but_last();
471         $errors = $this->end_capture();
472         // Verify outcome
473         $this->assertEqual('</h3></h2>', $html);
474         $this->assertEqual('', $errors);
475         // Tear down.
476         $stack->discard();
477     }
479     public function test_pop_all_but_last_only_one() {
480         // Set up.
481         $stack = new xhtml_container_stack();
482         $stack->push('test1', '</h1>');
483         // Exercise SUT.
484         $this->start_capture();
485         $html = $stack->pop_all_but_last();
486         $errors = $this->end_capture();
487         // Verify outcome
488         $this->assertEqual('', $html);
489         $this->assertEqual('', $errors);
490         // Tear down.
491         $stack->discard();
492     }
494     public function test_pop_all_but_last_empty() {
495         // Set up.
496         $stack = new xhtml_container_stack();
497         // Exercise SUT.
498         $this->start_capture();
499         $html = $stack->pop_all_but_last();
500         $errors = $this->end_capture();
501         // Verify outcome
502         $this->assertEqual('', $html);
503         $this->assertEqual('', $errors);
504     }
506     public function test_destruct() {
507         // Set up.
508         $stack = new xhtml_container_stack();
509         $stack->push('test1', '</somethingdistinctive>');
510         // Exercise SUT.
511         $this->start_capture();
512         $stack = null;
513         $errors = $this->end_capture();
514         // Verify outcome
515         $this->assertPattern('/<\/somethingdistinctive>/', $errors);
516     }
518     public function test_destruct_empty() {
519         // Set up.
520         $stack = new xhtml_container_stack();
521         // Exercise SUT.
522         $this->start_capture();
523         $stack = null;
524         $errors = $this->end_capture();
525         // Verify outcome
526         $this->assertEqual('', $errors);
527     }
529     public function test_discard() {
530         // Set up.
531         $stack = new xhtml_container_stack();
532         $stack->push('test1', '</somethingdistinctive>');
533         $stack->discard();
534         // Exercise SUT.
535         $this->start_capture();
536         $stack = null;
537         $errors = $this->end_capture();
538         // Verify outcome
539         $this->assertEqual('', $errors);
540     }
543 /**
544  * Unit tests for the core_renderer class.
545  *
546  * @copyright 2009 Tim Hunt
547  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
548  */
549 class core_renderer_test extends UnitTestCase {
551     public static $includecoverage = array('lib/outputrenderers.php', 'lib/outputcomponents.php');
552     protected $renderer;
554     public function setUp() {
555         parent::setUp();
556         $this->renderer = new core_renderer(new moodle_page);
557     }
559     public function test_select_simple() {
560         $select = html_select::make(array(10 => 'ten', 'c2' => 'two'), 'mymenu');
561         $html = $this->renderer->select($select);
562         $this->assert(new ContainsTagWithAttributes('select', array('class' => 'menumymenu select', 'name' => 'mymenu', 'id' => 'menumymenu')), $html);
563         $this->assert(new ContainsTagWithContents('option', 'ten'), $html);
564         $this->assert(new ContainsTagWithAttribute('option', 'value', '10'), $html);
565         $this->assert(new ContainsTagWithContents('option', 'two'), $html);
566         $this->assert(new ContainsTagWithAttribute('option', 'value', 'c2'), $html);
567     }
569     public function test_select_with_label() {
570         $select = html_select::make(array(10 => 'ten', 'c2' => 'two'), 'mymenu');
571         $select->set_label('Cool menu');
572         $html = $this->renderer->select($select);
573         $this->assert(new ContainsTagWithAttribute('label', 'for', $select->id), $html);
574         $this->assert(new ContainsTagWithContents('label', 'Cool menu'), $html);
575     }
577     public function test_select_yesno() {
578         $select = html_select::make_yes_no('question', 1);
579         $html = $this->renderer->select($select);
580         $this->assert(new ContainsTagWithAttributes('select', array('class' => 'menuquestion select', 'name' => 'question', 'id' => 'menuquestion')), $html);
581         $this->assert(new ContainsTagWithContents('option', get_string('choosedots')), $html);
582         $this->assert(new ContainsTagWithContents('option', get_string('yes')), $html);
583         $this->assert(new ContainsTagWithContents('option', get_string('no')), $html);
584         $this->assert(new ContainsTagWithAttributes('option', array('value' => '1', 'selected' => 'selected')), $html);
585     }
587     public function test_error_text() {
588         $html = $this->renderer->error_text('message');
589         $this->assert(new ContainsTagWithContents('span', 'message'), $html);
590         $this->assert(new ContainsTagWithAttribute('span', 'class', 'error'), $html);
591     }
593     public function test_error_text_blank() {
594         $html = $this->renderer->error_text('');
595         $this->assertEqual('', $html);
596     }
598     public function test_link_to_popup_empty_link() {
599         // Empty link object: link MUST have a text value
600         $link = new html_link();
601         $popupaction = new popup_action('click', 'http://test.com', 'my_popup');
602         $link->add_action($popupaction);
603         $this->expectException();
604         $html = $this->renderer->link_to_popup($link);
605     }
607     public function test_link_to_popup() {
608         $link = new html_link();
609         $link->text = 'Click here';
610         $link->url = 'http://test.com';
611         $link->title = 'Popup window';
612         $popupaction = new popup_action('click', 'http://test.com', 'my_popup');
613         $link->add_action($popupaction);
615         $html = $this->renderer->link_to_popup($link);
616         $expectedattributes = array('title' => 'Popup window', 'href' => 'http://test.com');
617         $this->assert(new ContainsTagWithAttributes('a', $expectedattributes), $html);
618         $this->assert(new ContainsTagWithContents('a', 'Click here'), $html);
620         // Try a different url for the link than for the popup
621         $link->url = 'http://otheraddress.com';
622         $html = $this->renderer->link_to_popup($link);
624         $this->assert(new ContainsTagWithAttribute('a', 'title', 'Popup window'), $html);
625         $this->assert(new ContainsTagWithAttribute('a', 'href', 'http://otheraddress.com'), $html);
626         $this->assert(new ContainsTagWithContents('a', 'Click here'), $html);
628         // Give it a moodle_url object instead of a string
629         $link->url = new moodle_url('http://otheraddress.com');
630         $html = $this->renderer->link_to_popup($link);
631         $this->assert(new ContainsTagWithAttribute('a', 'title', 'Popup window'), $html);
632         $this->assert(new ContainsTagWithAttribute('a', 'href', 'http://otheraddress.com'), $html);
633         $this->assert(new ContainsTagWithContents('a', 'Click here'), $html);
635     }
637     public function test_button() {
638         global $CFG;
639         $originalform = new html_form();
640         $originalform->button->text = 'Click Here';
641         $originalform->url = '/index.php';
643         $form = clone($originalform);
645         $html = $this->renderer->button($form);
646         $this->assert(new ContainsTagWithAttribute('div', 'class', 'singlebutton'), $html);
647         $this->assert(new ContainsTagWithAttributes('form', array('method' => 'post', 'action' => $CFG->wwwroot . '/index.php')), $html);
648         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
649         $this->assert(new ContainsTagWithAttributes('input', array('value' => 'Click Here', 'type' => 'submit')), $html);
651         $form = clone($originalform);
652         $form->button->confirmmessage = 'Are you sure?';
654         $html = $this->renderer->button($form);
655         $this->assert(new ContainsTagWithAttribute('div', 'class', 'singlebutton'), $html);
656         $this->assert(new ContainsTagWithAttributes('form', array('method' => 'post', 'action' => $CFG->wwwroot . '/index.php')), $html);
657         $this->assert(new ContainsTagWithAttribute('input', 'type', 'submit'), $html);
659         $form = clone($originalform);
660         $form->url = new moodle_url($form->url, array('var1' => 'value1', 'var2' => 'value2'));
661         $html = $this->renderer->button($form);
662         $this->assert(new ContainsTagWithAttributes('input', array('name' => 'var1', 'type' => 'hidden', 'value' => 'value1')), $html);
664     }
666     public function test_link() {
667         $link = new html_link();
668         $link->url = 'http://test.com';
669         $link->text = 'Resource 1';
671         $html = $this->renderer->link($link);
672         $this->assert(new ContainsTagWithAttribute('a', 'href', 'http://test.com'), $html);
673         $this->assert(new ContainsTagWithContents('a', 'Resource 1'), $html);
675         // Add a title
676         $link->title = 'Link to resource 1';
677         $html = $this->renderer->link($link);
678         $this->assert(new ContainsTagWithAttributes('a', array('title' => 'Link to resource 1', 'href' => 'http://test.com')), $html);
679         $this->assert(new ContainsTagWithContents('a', 'Resource 1'), $html);
681         // Use a moodle_url object instead of string
682         $link->url = new moodle_url($link->url);
683         $html = $this->renderer->link($link);
684         $this->assert(new ContainsTagWithAttributes('a', array('title' => 'Link to resource 1', 'href' => 'http://test.com')), $html);
685         $this->assert(new ContainsTagWithContents('a', 'Resource 1'), $html);
687         // Add a few classes to the link object
688         $link->add_classes('cool blue');
689         $html = $this->renderer->link($link);
690         $this->assert(new ContainsTagWithAttributes('a', array('title' => 'Link to resource 1', 'class' => 'cool blue', 'href' => 'http://test.com')), $html);
691         $this->assert(new ContainsTagWithContents('a', 'Resource 1'), $html);
693         // Simple use of link() without a html_link object
694         $html = $this->renderer->link($link->url->out(), $link->text);
695         $expected_html = '<a href="http://test.com">Resource 1</a>';
696         $this->assert(new ContainsTagWithAttribute('a', 'href', 'http://test.com'), $html);
697         $this->assert(new ContainsTagWithContents('a', 'Resource 1'), $html);
699         // Missing second param when first is a string: exception
700         $this->expectException();
701         $html = $this->renderer->link($link->url->out());
702     }
704     /**
705      * NOTE: consider the degree of detail in which we test HTML output, because
706      * the unit tests may be run under a different theme, with different HTML
707      * renderers. Maybe we should limit unit tests to standardwhite.
708      */
709     public function test_confirm() {
710         // Basic test with string URLs
711         $continueurl = 'http://www.test.com/index.php?continue=1';
712         $cancelurl = 'http://www.test.com/index.php?cancel=1';
713         $message = 'Are you sure?';
715         $html = $this->renderer->confirm($message, $continueurl, $cancelurl);
716         $this->assert(new ContainsTagWithAttributes('div', array('id' => 'notice', 'class' => 'box generalbox')), $html);
717         $this->assert(new ContainsTagWithContents('p', $message), $html);
718         $this->assert(new ContainsTagWithAttribute('div', 'class', 'buttons'), $html);
719         $this->assert(new ContainsTagWithAttribute('div', 'class', 'singlebutton'), $html);
720         $this->assert(new ContainsTagWithAttributes('form', array('method' => 'post', 'action' => 'http://www.test.com/index.php')), $html);
721         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'continue', 'value' => 1)), $html);
722         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
723         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'submit', 'value' => get_string('continue'), 'class' => 'singlebutton')), $html);
724         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'cancel', 'value' => 1)), $html);
725         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
726         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'submit', 'value' => get_string('cancel'), 'class' => 'singlebutton')), $html);
728         // Use html_forms with default values, should produce exactly the same output as above
729         $formcontinue = new html_form();
730         $formcancel = new html_form();
731         $formcontinue->url = new moodle_url($continueurl);
732         $formcancel->url = new moodle_url($cancelurl);
733         $formcontinue->button->text = get_string('continue');
734         $formcancel->button->text = get_string('cancel');
735         $html = $this->renderer->confirm($message, $formcontinue, $formcancel);
736         $this->assert(new ContainsTagWithAttributes('div', array('id' => 'notice', 'class' => 'box generalbox')), $html);
737         $this->assert(new ContainsTagWithContents('p', $message), $html);
738         $this->assert(new ContainsTagWithAttribute('div', 'class', 'buttons'), $html);
739         $this->assert(new ContainsTagWithAttribute('div', 'class', 'singlebutton'), $html);
740         $this->assert(new ContainsTagWithAttributes('form', array('method' => 'post', 'action' => 'http://www.test.com/index.php')), $html);
741         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'continue', 'value' => 1)), $html);
742         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
743         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'submit', 'value' => get_string('continue'), 'class' => 'singlebutton')), $html);
744         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'cancel', 'value' => 1)), $html);
745         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
746         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'submit', 'value' => get_string('cancel'), 'class' => 'singlebutton')), $html);
748         // Give the buttons some different labels
749         $formcontinue = new html_form();
750         $formcancel = new html_form();
751         $formcontinue->url = new moodle_url($continueurl);
752         $formcancel->url = new moodle_url($cancelurl);
753         $formcontinue->button->text = 'Continue anyway';
754         $formcancel->button->text = 'Wow OK, I get it, backing out!';
755         $html = $this->renderer->confirm($message, $formcontinue, $formcancel);
756         $this->assert(new ContainsTagWithAttributes('form', array('method' => 'post', 'action' => 'http://www.test.com/index.php')), $html);
757         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'continue', 'value' => 1)), $html);
758         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
759         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'submit', 'value' => $formcontinue->button->text, 'class' => 'singlebutton')), $html);
760         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'cancel', 'value' => 1)), $html);
761         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
762         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'submit', 'value' => $formcancel->button->text, 'class' => 'singlebutton')), $html);
764         // Change the method and add extra variables
765         $formcontinue = new html_form();
766         $formcancel = new html_form();
767         $formcontinue->button->text = get_string('continue');
768         $formcancel->button->text = get_string('cancel');
769         $formcontinue->url = new moodle_url($continueurl, array('var1' => 'val1', 'var2' => 'val2'));
770         $formcancel->url = new moodle_url($cancelurl, array('var3' => 'val3', 'var4' => 'val4'));
771         $html = $this->renderer->confirm($message, $formcontinue, $formcancel);
772         $this->assert(new ContainsTagWithAttributes('form', array('method' => 'post', 'action' => 'http://www.test.com/index.php')), $html);
773         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'continue', 'value' => 1)), $html);
774         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
775         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'var1', 'value' => 'val1')), $html);
776         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'var2', 'value' => 'val2')), $html);
777         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'submit', 'value' => get_string('continue'), 'class' => 'singlebutton')), $html);
778         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'cancel', 'value' => 1)), $html);
779         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())), $html);
780         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'submit', 'value' => get_string('cancel'), 'class' => 'singlebutton')), $html);
781         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'var3', 'value' => 'val3')), $html);
782         $this->assert(new ContainsTagWithAttributes('input', array('type' => 'hidden', 'name' => 'var4', 'value' => 'val4')), $html);
784     }
786     public function test_spacer() {
787         global $CFG;
789         $spacer = new html_image();
791         $html = $this->renderer->spacer($spacer);
792         $this->assert(new ContainsTagWithAttributes('img', array('class' => 'image spacer',
793                  'src' => $CFG->wwwroot . '/pix/spacer.gif',
794                  'alt' => ''
795                  )), $html);
796         $spacer = new html_image();
797         $spacer->src = $this->renderer->pix_url('myspacer');
798         $spacer->alt = 'sometext';
799         $spacer->add_class('my');
801         $html = $this->renderer->spacer($spacer);
803         $this->assert(new ContainsTagWithAttributes('img', array(
804                  'class' => 'my image spacer',
805                  'src' => $this->renderer->pix_url('myspacer'),
806                  'alt' => 'sometext')), $html);
808     }
810     public function test_paging_bar() {
811         global $CFG;
813         $totalcount = 5;
814         $perpage = 4;
815         $page = 1;
816         $baseurl = new moodle_url('/index.php');
817         $pagevar = 'mypage';
819         $pagingbar = new moodle_paging_bar();
820         $pagingbar->totalcount = $totalcount;
821         $pagingbar->page = $page;
822         $pagingbar->perpage = $perpage;
823         $pagingbar->baseurl = $baseurl;
824         $pagingbar->pagevar = $pagevar;
826         $originalbar = clone($pagingbar);
828         $html = $this->renderer->paging_bar($pagingbar);
830         $this->assert(new ContainsTagWithAttribute('div', 'class', 'paging'), $html);
831         // the 'Previous' link
832         $this->assert(new ContainsTagWithAttributes('a', array('class' => 'previous', 'href' => $baseurl->out().'?mypage=0')), $html);
833         // the numeric link to the previous page '1' (does not have the 'previous' class)
834         $this->assert(new ContainsTagWithAttributes('a', array('href' => $baseurl->out().'?mypage=0'), array('class' => 'previous')), $html);
835         // no link to the current page, it's the last page
836         $expectation = new ContainsTagWithAttributes('a', array('href' => $baseurl->out().'?mypage=1'), array());
837         $this->assertFalse($expectation->test($html));
839         // TODO test with more different parameters
840     }
842     public function test_html_list() {
843         $htmllist = new html_list();
844         $data = array('item1', 'item2', array('item1-1', 'item1-2'));
845         $htmllist->load_data($data);
846         $htmllist->items[2]->type = 'ordered';
847         $html = $this->renderer->htmllist($htmllist);
848     }
850     public function test_html_select() {
851         $options = array('var1' => 'value1', 'var2' => 'value2', 'var3' => 'value3');
852         $select = html_select::make($options, 'mymenu', 'var2');
853         $html = $this->renderer->select($select);
854         $this->assert(new ContainsTagWithAttributes('select', array('name' => 'mymenu')), $html);
855         $this->assert(new ContainsTagWithAttributes('option', array('value' => 'var1'), array('selected' => 'selected')), $html);
856         $this->assert(new ContainsTagWithAttributes('option', array('value' => 'var2', 'selected' => 'selected')), $html);
857         $this->assert(new ContainsTagWithAttributes('option', array('value' => 'var3'), array('selected' => 'selected')), $html);
858         $this->assert(new ContainsTagWithContents('option', 'value1'), $html);
859         $this->assert(new ContainsTagWithContents('option', 'value2'), $html);
860         $this->assert(new ContainsTagWithContents('option', 'value3'), $html);
862         $options = array('group1' => '--group1', 'var1' => 'value1', 'var2' => 'value2', 'group2' => '--', 'group2' => '--group2', 'var3' => 'value3', 'var4' => 'value4');
863         $select = html_select::make($options, 'mymenu', 'var2');
864         $html = $this->renderer->select($select);
865         $this->assert(new ContainsTagWithAttributes('select', array('name' => 'mymenu')), $html);
866         $this->assert(new ContainsTagWithAttributes('optgroup', array('label' => 'group1')), $html);
867         $this->assert(new ContainsTagWithAttributes('optgroup', array('label' => 'group2')), $html);
868         $this->assert(new ContainsTagWithAttributes('option', array('value' => 'var1'), array('selected' => 'selected')), $html);
869         $this->assert(new ContainsTagWithAttributes('option', array('value' => 'var2', 'selected' => 'selected')), $html);
870         $this->assert(new ContainsTagWithAttributes('option', array('value' => 'var3'), array('selected' => 'selected')), $html);
871         $this->assert(new ContainsTagWithAttributes('option', array('value' => 'var4'), array('selected' => 'selected')), $html);
872         $this->assert(new ContainsTagWithContents('option', 'value1'), $html);
873         $this->assert(new ContainsTagWithContents('option', 'value2'), $html);
874         $this->assert(new ContainsTagWithContents('option', 'value3'), $html);
875         $this->assert(new ContainsTagWithContents('option', 'value4'), $html);
876     }
878     public function test_userpicture() {
879         global $CFG;
880         // Set up the user with the required fields
881         $user = new stdClass();
882         $user->firstname = 'Test';
883         $user->lastname = 'User';
884         $user->picture = false;
885         $user->imagealt = false;
886         $user->id = 1;
887         $userpic = new user_picture();
888         $userpic->user = $user;
889         $userpic->courseid = 1;
890         $userpic->url = true;
891         // Setting popup to true adds JS for the link to open in a popup
892         $userpic->popup = true;
893         $html = $this->renderer->user_picture($userpic);
894         $this->assert(new ContainsTagWithAttributes('a', array('title' => 'Test User', 'href' => $CFG->wwwroot.'/user/view.php?id=1&course=1')), $html);
895     }
897     public function test_heading_with_help() {
898         $originalicon = new help_icon();
899         $originalicon->page = 'myhelppage';
900         $originalicon->text = 'Cool help text';
902         $helpicon = clone($originalicon);
903         $html = $this->renderer->heading_with_help($helpicon);
904         $this->assert(new ContainsTagWithAttribute('div', 'class', 'heading-with-help'), $html);
905         $this->assert(new ContainsTagWithAttribute('span', 'class', 'helplink'), $html);
906         $this->assert(new ContainsTagWithAttribute('h2', 'class', 'main help'), $html);
907         $this->assert(new ContainsTagWithAttributes('img', array('class' => 'iconhelp image', 'src' => $this->renderer->pix_url('help'))), $html);
908         $this->assert(new ContainsTagWithContents('h2', 'Cool help text'), $html);
910         $helpicon = clone($originalicon);
911         $helpicon->image = false;
913         $html = $this->renderer->heading_with_help($helpicon);
914         $this->assert(new ContainsTagWithAttribute('div', 'class', 'heading-with-help'), $html);
915         $this->assert(new ContainsTagWithAttribute('span', 'class', 'helplink'), $html);
916         $this->assert(new ContainsTagWithAttribute('h2', 'class', 'main help'), $html);
917         $this->assert(new ContainsTagWithAttributes('img', array('class' => 'iconhelp image', 'src' => $this->renderer->pix_url('help'))), $html);
918         $this->assert(new ContainsTagWithContents('h2', 'Cool help text'), $html);
919     }
922 EOT;