MDL-41551 blocks: added tracking and recognition of custom block regions
[moodle.git] / lib / tests / blocklib_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  * Tests for the block_manager class in ../blocklib.php.
19  *
20  * @package   core
21  * @category  phpunit
22  * @copyright 2009 Tim Hunt
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
29 require_once($CFG->libdir . '/pagelib.php');
30 require_once($CFG->libdir . '/blocklib.php');
31 require_once($CFG->dirroot . '/blocks/moodleblock.class.php');
34 /**
35  * Test various block related classes.
36  */
37 class core_blocklib_testcase extends advanced_testcase {
38     protected $testpage;
39     protected $blockmanager;
40     protected $isediting = null;
42     protected function setUp() {
43         parent::setUp();
44         $this->testpage = new moodle_page();
45         $this->testpage->set_context(context_system::instance());
46         $this->testpage->set_pagetype('phpunit-block-test');
47         $this->blockmanager = new testable_block_manager($this->testpage);
48     }
50     protected function tearDown() {
51         $this->testpage = null;
52         $this->blockmanager = null;
53         parent::tearDown();
54     }
56     protected function purge_blocks() {
57         global $DB;
58         $this->resetAfterTest();
60         $bis = $DB->get_records('block_instances');
61         foreach ($bis as $instance) {
62             blocks_delete_instance($instance);
63         }
64     }
66     public function test_no_regions_initially() {
67         // Exercise SUT & Validate.
68         $this->assertEquals(array(), $this->blockmanager->get_regions());
69     }
71     public function test_add_region() {
72         // Exercise SUT.
73         $this->blockmanager->add_region('a-region-name', false);
74         // Validate.
75         $this->assertEquals(array('a-region-name'), $this->blockmanager->get_regions());
76     }
78     public function test_add_regions() {
79         // Set up fixture.
80         $regions = array('a-region', 'another-region');
81         // Exercise SUT.
82         $this->blockmanager->add_regions($regions, false);
83         // Validate.
84         $this->assertEquals($regions, $this->blockmanager->get_regions(), '', 0, 10, true);
85     }
87     public function test_add_region_twice() {
88         // Exercise SUT.
89         $this->blockmanager->add_region('a-region-name', false);
90         $this->blockmanager->add_region('another-region', false);
91         // Validate.
92         $this->assertEquals(array('a-region-name', 'another-region'), $this->blockmanager->get_regions(), '', 0, 10, true);
93     }
95     /**
96      * @expectedException coding_exception
97      */
98     public function test_cannot_add_region_after_loaded() {
99         // Set up fixture.
100         $this->blockmanager->mark_loaded();
101         // Exercise SUT.
102         $this->blockmanager->add_region('too-late', false);
103     }
105     /**
106      * Testing adding a custom region.
107      */
108     public function test_add_custom_region() {
109         global $SESSION;
110         // Exercise SUT.
111         $this->blockmanager->add_region('a-custom-region-name');
112         // Validate.
113         $this->assertEquals(array('a-custom-region-name'), $this->blockmanager->get_regions());
114         $this->assertTrue(isset($SESSION->custom_block_regions));
115         $this->assertArrayHasKey('phpunit-block-test', $SESSION->custom_block_regions);
116         $this->assertTrue(in_array('a-custom-region-name', $SESSION->custom_block_regions['phpunit-block-test']));
118     }
120     /**
121      * Test adding two custom regions using add_regions method.
122      */
123     public function test_add_custom_regions() {
124         global $SESSION;
125         // Set up fixture.
126         $regions = array('a-region', 'another-custom-region');
127         // Exercise SUT.
128         $this->blockmanager->add_regions($regions);
129         // Validate.
130         $this->assertEquals($regions, $this->blockmanager->get_regions(), '', 0, 10, true);
131         $this->assertTrue(isset($SESSION->custom_block_regions));
132         $this->assertArrayHasKey('phpunit-block-test', $SESSION->custom_block_regions);
133         $this->assertTrue(in_array('another-custom-region', $SESSION->custom_block_regions['phpunit-block-test']));
134     }
136     /**
137      * Test adding two custom block regions.
138      */
139     public function test_add_custom_region_twice() {
140         // Exercise SUT.
141         $this->blockmanager->add_region('a-custom-region-name');
142         $this->blockmanager->add_region('another-custom-region');
143         // Validate.
144         $this->assertEquals(
145             array('a-custom-region-name', 'another-custom-region'),
146             $this->blockmanager->get_regions(),
147             '', 0, 10, true
148         );
149     }
151     /**
152      * Test to ensure that we cannot add a region after the blocks have been loaded.
153      * @expectedException coding_exception
154      */
155     public function test_cannot_add_custom_region_after_loaded() {
156         // Set up fixture.
157         $this->blockmanager->mark_loaded();
158         // Exercise SUT.
159         $this->blockmanager->add_region('too-late');
160     }
162     public function test_set_default_region() {
163         // Set up fixture.
164         $this->blockmanager->add_region('a-region-name', false);
165         // Exercise SUT.
166         $this->blockmanager->set_default_region('a-region-name');
167         // Validate.
168         $this->assertEquals('a-region-name', $this->blockmanager->get_default_region());
169     }
171     /**
172      * @expectedException coding_exception
173      */
174     public function test_cannot_set_unknown_region_as_default() {
175         // Exercise SUT.
176         $this->blockmanager->set_default_region('a-region-name');
177     }
179     /**
180      * @expectedException coding_exception
181      */
182     public function test_cannot_change_default_region_after_loaded() {
183         // Set up fixture.
184         $this->blockmanager->mark_loaded();
185         // Exercise SUT.
186         $this->blockmanager->set_default_region('too-late');
187     }
189     public function test_matching_page_type_patterns() {
190         $this->assertEquals(array('site-index', 'site-index-*', 'site-*', '*'),
191             matching_page_type_patterns('site-index'), '', 0, 10, true);
193         $this->assertEquals(array('mod-quiz-report-overview', 'mod-quiz-report-overview-*', 'mod-quiz-report-*', 'mod-quiz-*', 'mod-*', '*'),
194             matching_page_type_patterns('mod-quiz-report-overview'), '', 0, 10, true);
196         $this->assertEquals(array('mod-forum-view', 'mod-*-view', 'mod-forum-view-*', 'mod-forum-*', 'mod-*', '*'),
197             matching_page_type_patterns('mod-forum-view'), '', 0, 10, true);
199         $this->assertEquals(array('mod-forum-index', 'mod-*-index', 'mod-forum-index-*', 'mod-forum-*', 'mod-*', '*'),
200             matching_page_type_patterns('mod-forum-index'), '', 0, 10, true);
201     }
203     protected function get_a_page_and_block_manager($regions, $context, $pagetype, $subpage = '') {
204         $page = new moodle_page;
205         $page->set_context($context);
206         $page->set_pagetype($pagetype);
207         $page->set_subpage($subpage);
209         $blockmanager = new testable_block_manager($page);
210         $blockmanager->add_regions($regions, false);
211         $blockmanager->set_default_region($regions[0]);
213         return array($page, $blockmanager);
214     }
216     protected function get_a_known_block_type() {
217         global $DB;
218         $block = new stdClass;
219         $block->name = 'ablocktype';
220         $DB->insert_record('block', $block);
221         return $block->name;
222     }
224     protected function assertContainsBlocksOfType($typearray, $blockarray) {
225         if (!$this->assertEquals(count($typearray), count($blockarray), "Blocks array contains the wrong number of elements %s.")) {
226             return;
227         }
228         $types = array_values($typearray);
229         $i = 0;
230         foreach ($blockarray as $block) {
231             $blocktype = $types[$i];
232             $this->assertEquals($blocktype, $block->name(), "Block types do not match at postition $i %s.");
233             $i++;
234         }
235     }
237     public function test_empty_initially() {
238         $this->purge_blocks();
240         // Set up fixture.
241         list($page, $blockmanager) = $this->get_a_page_and_block_manager(array('a-region'),
242             context_system::instance(), 'page-type');
243         // Exercise SUT.
244         $blockmanager->load_blocks();
245         // Validate.
246         $blocks = $blockmanager->get_loaded_blocks();
247         $this->assertEquals(array('a-region' => array()), $blocks);
248     }
250     public function test_adding_and_retrieving_one_block() {
251         $this->purge_blocks();
253         // Set up fixture.
254         $regionname = 'a-region';
255         $blockname = $this->get_a_known_block_type();
256         $context = context_system::instance();
258         list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
259             $context, 'page-type');
261         // Exercise SUT.
262         $blockmanager->add_block($blockname, $regionname, 0, false);
263         $blockmanager->load_blocks();
264         // Validate.
265         $blocks = $blockmanager->get_blocks_for_region($regionname);
266         $this->assertContainsBlocksOfType(array($blockname), $blocks);
267     }
269     public function test_adding_and_retrieving_two_blocks() {
270         $this->purge_blocks();
272         // Set up fixture.
273         $regionname = 'a-region';
274         $blockname = $this->get_a_known_block_type();
275         $context = context_system::instance();
277         list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
278             $context, 'page-type');
280         // Exercise SUT.
281         $blockmanager->add_block($blockname, $regionname, 0, false);
282         $blockmanager->add_block($blockname, $regionname, 1, false);
283         $blockmanager->load_blocks();
284         // Validate.
285         $blocks = $blockmanager->get_blocks_for_region($regionname);
286         $this->assertContainsBlocksOfType(array($blockname, $blockname), $blocks);
287     }
289     public function test_block_not_included_in_different_context() {
290         $this->purge_blocks();
292         // Set up fixture.
293         $syscontext = context_system::instance();
294         $cat = $this->getDataGenerator()->create_category(array('name' => 'testcategory'));
295         $fakecontext = context_coursecat::instance($cat->id);
296         $regionname = 'a-region';
297         $blockname = $this->get_a_known_block_type();
299         list($addpage, $addbm) = $this->get_a_page_and_block_manager(array($regionname), $fakecontext, 'page-type');
300         list($viewpage, $viewbm) = $this->get_a_page_and_block_manager(array($regionname), $syscontext, 'page-type');
302         $addbm->add_block($blockname, $regionname, 0, false);
304         // Exercise SUT.
305         $viewbm->load_blocks();
306         // Validate.
307         $blocks = $viewbm->get_blocks_for_region($regionname);
308         $this->assertContainsBlocksOfType(array(), $blocks);
309     }
311     public function test_block_included_in_sub_context() {
312         $this->purge_blocks();
314         // Set up fixture.
315         $syscontext = context_system::instance();
316         $childcontext = context_coursecat::instance(1);
317         $regionname = 'a-region';
318         $blockname = $this->get_a_known_block_type();
320         list($addpage, $addbm) = $this->get_a_page_and_block_manager(array($regionname), $syscontext, 'page-type');
321         list($viewpage, $viewbm) = $this->get_a_page_and_block_manager(array($regionname), $childcontext, 'page-type');
323         $addbm->add_block($blockname, $regionname, 0, true);
325         // Exercise SUT.
326         $viewbm->load_blocks();
327         // Validate.
328         $blocks = $viewbm->get_blocks_for_region($regionname);
329         $this->assertContainsBlocksOfType(array($blockname), $blocks);
330     }
332     public function test_block_not_included_on_different_page_type() {
333         $this->purge_blocks();
335         // Set up fixture.
336         $syscontext = context_system::instance();
337         $regionname = 'a-region';
338         $blockname = $this->get_a_known_block_type();
340         list($addpage, $addbm) = $this->get_a_page_and_block_manager(array($regionname), $syscontext, 'page-type');
341         list($viewpage, $viewbm) = $this->get_a_page_and_block_manager(array($regionname), $syscontext, 'other-page-type');
343         $addbm->add_block($blockname, $regionname, 0, true);
345         // Exercise SUT.
346         $viewbm->load_blocks();
347         // Validate.
348         $blocks = $viewbm->get_blocks_for_region($regionname);
349         $this->assertContainsBlocksOfType(array(), $blocks);
350     }
352     public function test_block_not_included_on_different_sub_page() {
353         $this->purge_blocks();
355         // Set up fixture.
356         $regionname = 'a-region';
357         $blockname = $this->get_a_known_block_type();
358         $syscontext = context_system::instance();
360         list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
361             $syscontext, 'page-type', 'sub-page');
363         $blockmanager->add_block($blockname, $regionname, 0, true, $page->pagetype, 'other-sub-page');
365         // Exercise SUT.
366         $blockmanager->load_blocks();
367         // Validate.
368         $blocks = $blockmanager->get_blocks_for_region($regionname);
369         $this->assertContainsBlocksOfType(array(), $blocks);
370     }
372     public function test_block_included_with_explicit_sub_page() {
373         $this->purge_blocks();
375         // Set up fixture.
376         $regionname = 'a-region';
377         $blockname = $this->get_a_known_block_type();
378         $syscontext = context_system::instance();
380         list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
381             $syscontext, 'page-type', 'sub-page');
383         $blockmanager->add_block($blockname, $regionname, 0, true, $page->pagetype, $page->subpage);
385         // Exercise SUT.
386         $blockmanager->load_blocks();
387         // Validate.
388         $blocks = $blockmanager->get_blocks_for_region($regionname);
389         $this->assertContainsBlocksOfType(array($blockname), $blocks);
390     }
392     public function test_block_included_with_page_type_pattern() {
393         $this->purge_blocks();
395         // Set up fixture.
396         $regionname = 'a-region';
397         $blockname = $this->get_a_known_block_type();
398         $syscontext = context_system::instance();
400         list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
401             $syscontext, 'page-type', 'sub-page');
403         $blockmanager->add_block($blockname, $regionname, 0, true, 'page-*', $page->subpage);
405         // Exercise SUT.
406         $blockmanager->load_blocks();
407         // Validate.
408         $blocks = $blockmanager->get_blocks_for_region($regionname);
409         $this->assertContainsBlocksOfType(array($blockname), $blocks);
410     }
413 /**
414  * Test-specific subclass to make some protected things public.
415  */
416 class testable_block_manager extends block_manager {
418     public function mark_loaded() {
419         $this->birecordsbyregion = array();
420     }
421     public function get_loaded_blocks() {
422         return $this->birecordsbyregion;
423     }
426 /**
427  * Test-specific subclass to make some protected things public.
428  */
429 class block_ablocktype extends block_base {
430     public function init() {
431     }