MDL-67271 core: Add test to find missing SVG icons
[moodle.git] / lib / tests / context_helper_test.php
blob7033d52a2af5680b442f48f55667bd26d272fa39
1 <?php
2 // This file is part of Moodle - https://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.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <https://www.gnu.org/licenses/>.
17 namespace core;
19 /**
20 * Unit tests for context helper class.
22 * NOTE: more tests are in lib/tests/accesslib_test.php
24 * @package core
25 * @copyright Petr Skoda
26 * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 * @coversDefaultClass \core\context_helper
29 class context_helper_test extends \advanced_testcase {
30 /**
31 * Tests covered method.
32 * @covers ::parse_external_level
34 public function test_parse_external_level() {
35 $this->assertSame(context\system::class, context_helper::parse_external_level('system'));
36 $this->assertSame(context\system::class, context_helper::parse_external_level(CONTEXT_SYSTEM));
37 $this->assertSame(context\system::class, context_helper::parse_external_level((string)CONTEXT_SYSTEM));
39 $this->assertSame(context\user::class, context_helper::parse_external_level('user'));
40 $this->assertSame(context\user::class, context_helper::parse_external_level(CONTEXT_USER));
41 $this->assertSame(context\user::class, context_helper::parse_external_level((string)CONTEXT_USER));
43 $this->assertSame(context\coursecat::class, context_helper::parse_external_level('coursecat'));
44 $this->assertSame(context\coursecat::class, context_helper::parse_external_level(CONTEXT_COURSECAT));
45 $this->assertSame(context\coursecat::class, context_helper::parse_external_level((string)CONTEXT_COURSECAT));
47 $this->assertSame(context\course::class, context_helper::parse_external_level('course'));
48 $this->assertSame(context\course::class, context_helper::parse_external_level(CONTEXT_COURSE));
49 $this->assertSame(context\course::class, context_helper::parse_external_level((string)CONTEXT_COURSE));
51 $this->assertSame(context\module::class, context_helper::parse_external_level('module'));
52 $this->assertSame(context\module::class, context_helper::parse_external_level(CONTEXT_MODULE));
53 $this->assertSame(context\module::class, context_helper::parse_external_level((string)CONTEXT_MODULE));
55 $this->assertSame(context\block::class, context_helper::parse_external_level('block'));
56 $this->assertSame(context\block::class, context_helper::parse_external_level(CONTEXT_BLOCK));
57 $this->assertSame(context\block::class, context_helper::parse_external_level((string)CONTEXT_BLOCK));
59 $this->assertNull(context_helper::parse_external_level('core_system'));
60 $this->assertNull(context_helper::parse_external_level('xsystem'));
61 $this->assertNull(context_helper::parse_external_level(1));
62 $this->assertNull(context_helper::parse_external_level(''));
65 /**
66 * Tests covered method.
67 * @covers ::resolve_behat_reference
69 public function test_resolve_behat_reference() {
70 $this->assertNull(context_helper::resolve_behat_reference('blahbla', 'blahbla'));
71 $this->assertNull(context_helper::resolve_behat_reference('', ''));
72 $this->assertNull(context_helper::resolve_behat_reference('0', ''));
74 $syscontext = context\system::instance();
75 $result = context_helper::resolve_behat_reference('System', '');
76 $this->assertSame($syscontext->id, $result->id);
78 $syscontext = context\system::instance();
79 $result = context_helper::resolve_behat_reference('10', '');
80 $this->assertSame($syscontext->id, $result->id);
82 // The rest is tested in each context class test.
85 /**
86 * Tests covered method.
87 * @covers ::get_class_for_level
89 public function test_get_class_for_level() {
90 $this->assertSame(context\system::class, context_helper::get_class_for_level(CONTEXT_SYSTEM));
91 $this->assertSame(context\system::class, context_helper::get_class_for_level((string)CONTEXT_SYSTEM));
93 $this->assertSame(context\user::class, context_helper::get_class_for_level(CONTEXT_USER));
94 $this->assertSame(context\user::class, context_helper::get_class_for_level((string)CONTEXT_USER));
96 $this->assertSame(context\coursecat::class, context_helper::get_class_for_level(CONTEXT_COURSECAT));
97 $this->assertSame(context\coursecat::class, context_helper::get_class_for_level((string)CONTEXT_COURSECAT));
99 $this->assertSame(context\course::class, context_helper::get_class_for_level(CONTEXT_COURSE));
100 $this->assertSame(context\course::class, context_helper::get_class_for_level((string)CONTEXT_COURSE));
102 $this->assertSame(context\module::class, context_helper::get_class_for_level(CONTEXT_MODULE));
103 $this->assertSame(context\module::class, context_helper::get_class_for_level((string)CONTEXT_MODULE));
105 $this->assertSame(context\block::class, context_helper::get_class_for_level(CONTEXT_BLOCK));
106 $this->assertSame(context\block::class, context_helper::get_class_for_level((string)CONTEXT_BLOCK));
108 try {
109 context_helper::get_class_for_level(1);
110 $this->fail('Exception expected if level does not exist');
111 } catch (\moodle_exception $e) {
112 $this->assertInstanceOf(\coding_exception::class, $e);
113 $this->assertSame('Coding error detected, it must be fixed by a programmer: Invalid context level specified',
114 $e->getMessage());
119 * Tests covered method.
120 * @covers ::get_all_levels
122 public function test_get_all_levels() {
123 $levels = context_helper::get_all_levels();
125 $this->assertArrayHasKey(CONTEXT_SYSTEM, $levels);
126 $this->assertSame(context\system::class, $levels[CONTEXT_SYSTEM]);
128 $this->assertArrayHasKey(CONTEXT_USER, $levels);
129 $this->assertSame(context\user::class, $levels[CONTEXT_USER]);
131 $this->assertArrayHasKey(CONTEXT_COURSECAT, $levels);
132 $this->assertSame(context\coursecat::class, $levels[CONTEXT_COURSECAT]);
134 $this->assertArrayHasKey(CONTEXT_COURSE, $levels);
135 $this->assertSame(context\course::class, $levels[CONTEXT_COURSE]);
137 $this->assertArrayHasKey(CONTEXT_MODULE, $levels);
138 $this->assertSame(context\module::class, $levels[CONTEXT_MODULE]);
140 $this->assertArrayHasKey(CONTEXT_BLOCK, $levels);
141 $this->assertSame(context\block::class, $levels[CONTEXT_BLOCK]);
143 $sorted = $levels;
144 ksort($sorted, SORT_NUMERIC);
145 $block = $sorted[CONTEXT_BLOCK];
146 unset($sorted[CONTEXT_BLOCK]);
147 $sorted[CONTEXT_BLOCK] = $block;
148 $this->assertSame(array_keys($sorted), array_keys($levels));
150 // Make sure level is set properly.
151 foreach ($levels as $level => $classname) {
152 $this->assertEquals($level, $classname::LEVEL);
153 if ($level != CONTEXT_SYSTEM) {
154 $this->assertGreaterThan(CONTEXT_SYSTEM, $level);
160 * Tests covered method.
161 * @covers ::get_child_levels
163 public function test_get_child_levels() {
164 $alllevels = context_helper::get_all_levels();
166 $childlevels = context_helper::get_child_levels(CONTEXT_SYSTEM);
167 $this->assertSame(count($alllevels) - 1, count($childlevels));
169 $childlevels = context_helper::get_child_levels(CONTEXT_USER);
170 $this->assertNotContains(CONTEXT_SYSTEM, $childlevels);
171 $this->assertNotContains(CONTEXT_USER, $childlevels);
172 $this->assertNotContains(CONTEXT_COURSECAT, $childlevels);
173 $this->assertNotContains(CONTEXT_COURSE, $childlevels);
174 $this->assertNotContains(CONTEXT_MODULE, $childlevels);
175 $this->assertContains(CONTEXT_BLOCK, $childlevels);
177 $childlevels = context_helper::get_child_levels(CONTEXT_COURSECAT);
178 $this->assertNotContains(CONTEXT_SYSTEM, $childlevels);
179 $this->assertNotContains(CONTEXT_USER, $childlevels);
180 $this->assertContains(CONTEXT_COURSECAT, $childlevels);
181 $this->assertContains(CONTEXT_COURSE, $childlevels);
182 $this->assertContains(CONTEXT_MODULE, $childlevels);
183 $this->assertContains(CONTEXT_BLOCK, $childlevels);
185 $childlevels = context_helper::get_child_levels(CONTEXT_COURSE);
186 $this->assertNotContains(CONTEXT_SYSTEM, $childlevels);
187 $this->assertNotContains(CONTEXT_USER, $childlevels);
188 $this->assertNotContains(CONTEXT_COURSECAT, $childlevels);
189 $this->assertNotContains(CONTEXT_COURSE, $childlevels);
190 $this->assertContains(CONTEXT_MODULE, $childlevels);
191 $this->assertContains(CONTEXT_BLOCK, $childlevels);
193 $childlevels = context_helper::get_child_levels(CONTEXT_MODULE);
194 $this->assertNotContains(CONTEXT_SYSTEM, $childlevels);
195 $this->assertNotContains(CONTEXT_USER, $childlevels);
196 $this->assertNotContains(CONTEXT_COURSECAT, $childlevels);
197 $this->assertNotContains(CONTEXT_COURSE, $childlevels);
198 $this->assertNotContains(CONTEXT_MODULE, $childlevels);
199 $this->assertContains(CONTEXT_BLOCK, $childlevels);
201 $childlevels = context_helper::get_child_levels(CONTEXT_BLOCK);
202 $this->assertCount(0, $childlevels);
206 * Tests covered method.
207 * @covers ::get_compatible_levels
209 public function test_get_compatible_levels() {
210 $levels = context_helper::get_compatible_levels('manager');
211 $this->assertContains(CONTEXT_SYSTEM, $levels);
212 $this->assertNotContains(CONTEXT_USER, $levels);
213 $this->assertContains(CONTEXT_COURSECAT, $levels);
214 $this->assertContains(CONTEXT_COURSE, $levels);
215 $this->assertNotContains(CONTEXT_MODULE, $levels);
216 $this->assertNotContains(CONTEXT_BLOCK, $levels);
218 $levels = context_helper::get_compatible_levels('coursecreator');
219 $this->assertContains(CONTEXT_SYSTEM, $levels);
220 $this->assertNotContains(CONTEXT_USER, $levels);
221 $this->assertContains(CONTEXT_COURSECAT, $levels);
222 $this->assertNotContains(CONTEXT_COURSE, $levels);
223 $this->assertNotContains(CONTEXT_MODULE, $levels);
224 $this->assertNotContains(CONTEXT_BLOCK, $levels);
226 $levels = context_helper::get_compatible_levels('editingteacher');
227 $this->assertNotContains(CONTEXT_SYSTEM, $levels);
228 $this->assertNotContains(CONTEXT_USER, $levels);
229 $this->assertNotContains(CONTEXT_COURSECAT, $levels);
230 $this->assertContains(CONTEXT_COURSE, $levels);
231 $this->assertContains(CONTEXT_MODULE, $levels);
232 $this->assertNotContains(CONTEXT_BLOCK, $levels);
234 $levels = context_helper::get_compatible_levels('teacher');
235 $this->assertNotContains(CONTEXT_SYSTEM, $levels);
236 $this->assertNotContains(CONTEXT_USER, $levels);
237 $this->assertNotContains(CONTEXT_COURSECAT, $levels);
238 $this->assertContains(CONTEXT_COURSE, $levels);
239 $this->assertContains(CONTEXT_MODULE, $levels);
240 $this->assertNotContains(CONTEXT_BLOCK, $levels);
242 $levels = context_helper::get_compatible_levels('student');
243 $this->assertNotContains(CONTEXT_SYSTEM, $levels);
244 $this->assertNotContains(CONTEXT_USER, $levels);
245 $this->assertNotContains(CONTEXT_COURSECAT, $levels);
246 $this->assertContains(CONTEXT_COURSE, $levels);
247 $this->assertContains(CONTEXT_MODULE, $levels);
248 $this->assertNotContains(CONTEXT_BLOCK, $levels);
250 $levels = context_helper::get_compatible_levels('user');
251 $this->assertCount(0, $levels);
253 $levels = context_helper::get_compatible_levels('guest');
254 $this->assertCount(0, $levels);
256 $levels = context_helper::get_compatible_levels('frontpage');
257 $this->assertCount(0, $levels);
261 * Tests covered method.
262 * @covers ::cleanup_instances
264 public function test_cleanup_instances() {
265 global $DB;
267 $this->resetAfterTest();
268 $this->preventResetByRollback();
270 $prevcount = $DB->count_records('context', []);
271 context_helper::cleanup_instances();
272 $count = $DB->count_records('context', []);
273 $this->assertSame($prevcount, $count);
275 // Insert bogus records for each level and see if they get removed,
276 // more test should be in tests for each context level.
277 $alllevels = context_helper::get_all_levels();
278 foreach ($alllevels as $classname) {
279 if ($classname::LEVEL == CONTEXT_SYSTEM) {
280 continue;
282 $record = new \stdClass();
283 $record->contextlevel = $classname::LEVEL;
284 $record->instanceid = 9999999999;
285 $record->path = null;
286 $record->depth = '2';
287 $record->id = $DB->insert_record('context', $record);
288 $DB->set_field('context', 'path', SYSCONTEXTID . '/' . $record->id, ['id' => $record->id]);
290 context_helper::cleanup_instances();
291 $count = $DB->count_records('context', []);
292 $this->assertSame($prevcount, $count);
296 * Tests covered method.
297 * @covers ::create_instances
299 public function test_create_instances() {
300 global $DB;
302 $this->resetAfterTest();
303 $this->preventResetByRollback();
305 $user = $this->getDataGenerator()->create_user();
306 $usercontext = context\user::instance($user->id);
307 $category = $this->getDataGenerator()->create_category();
308 $categorycontext = context\coursecat::instance($category->id);
309 $course = $this->getDataGenerator()->create_course();
310 $coursecontext = context\course::instance($course->id);
311 $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id]);
312 $pagecontext = context\module::instance($page->cmid);
314 $prevcount = $DB->count_records('context', []);
315 $DB->delete_records('context', ['id' => $usercontext->id]);
316 $DB->delete_records('context', ['id' => $categorycontext->id]);
317 $DB->delete_records('context', ['id' => $coursecontext->id]);
318 $DB->delete_records('context', ['id' => $pagecontext->id]);
320 context_helper::create_instances();
321 $count = $DB->count_records('context', []);
322 $this->assertSame($prevcount, $count);
326 * Tests covered method.
327 * @covers ::build_all_paths
329 public function test_build_all_paths() {
330 $this->resetAfterTest();
331 $this->preventResetByRollback();
333 // Just make sure there are no fatal errors for now.
334 context_helper::build_all_paths(true);
335 context_helper::build_all_paths();
339 * Tests covered method.
340 * @covers ::reset_caches
342 public function test_reset_caches() {
343 $this->resetAfterTest();
344 $this->preventResetByRollback();
346 // Just make sure there are no fatal errors for now.
347 context_helper::reset_caches();
351 * Tests covered method.
352 * @covers ::get_preload_record_columns
354 public function test_get_preload_record_columns() {
355 $expected = array (
356 'testalias.id' => 'ctxid',
357 'testalias.path' => 'ctxpath',
358 'testalias.depth' => 'ctxdepth',
359 'testalias.contextlevel' => 'ctxlevel',
360 'testalias.instanceid' => 'ctxinstance',
361 'testalias.locked' => 'ctxlocked',
363 $result = context_helper::get_preload_record_columns('testalias');
364 $this->assertSame($expected, $result);
368 * Tests covered method.
369 * @covers ::get_preload_record_columns_sql
371 public function test_get_preload_record_columns_sql() {
372 global $DB;
374 $result = context_helper::get_preload_record_columns_sql('testalias');
375 $expected = 'testalias.id AS ctxid, testalias.path AS ctxpath, testalias.depth AS ctxdepth,'
376 .' testalias.contextlevel AS ctxlevel, testalias.instanceid AS ctxinstance, testalias.locked AS ctxlocked';
377 $this->assertSame($expected, $result);
379 $sql = "SELECT id, $result
380 FROM {context} testalias";
381 $DB->get_records_sql($sql, []);
385 * Tests covered method.
386 * @covers ::preload_from_record
388 public function test_preload_from_record() {
389 global $DB;
391 $select = context_helper::get_preload_record_columns_sql('testalias');
392 $sql = "SELECT id, $select
393 FROM {context} testalias";
394 $records = $DB->get_records_sql($sql, []);
395 foreach ($records as $record) {
396 $this->assertNull(context_helper::preload_from_record($record));
399 $this->assertDebuggingNotCalled();
400 $record = reset($records);
401 unset($record->ctxlevel);
402 $this->assertNull(context_helper::preload_from_record($record));
406 * Tests covered method.
407 * @covers ::preload_contexts_by_id
409 public function test_preload_contexts_by_id() {
410 global $DB;
412 $contextids = $DB->get_fieldset_sql("SELECT id FROM {context}", []);
413 context_helper::preload_contexts_by_id($contextids);
414 context_helper::preload_contexts_by_id($contextids);
416 context_helper::reset_caches();
417 context_helper::preload_contexts_by_id($contextids);
421 * Tests covered method.
422 * @covers ::preload_course
424 public function test_preload_course() {
425 global $SITE;
426 context_helper::preload_course($SITE->id);
430 * Tests covered method.
431 * @covers ::delete_instance
433 public function test_delete_instance() {
434 $this->resetAfterTest();
436 $user = $this->getDataGenerator()->create_user();
437 $category = $this->getDataGenerator()->create_category();
438 $course = $this->getDataGenerator()->create_course();
439 $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
441 // This is a bit silly test, it might start failing in the future
442 // because the instances are not deleted before deleting the contexts.
443 context_helper::delete_instance(CONTEXT_USER, $user->id);
444 context_helper::delete_instance(CONTEXT_COURSECAT, $category->id);
445 context_helper::delete_instance(CONTEXT_COURSE, $course->id);
446 context_helper::delete_instance(CONTEXT_MODULE, $page->cmid);
450 * Tests covered method.
451 * @covers ::get_level_name
453 public function test_get_level_name() {
454 $allevels = context_helper::get_all_levels();
455 foreach ($allevels as $level => $classname) {
456 $name = context_helper::get_level_name($level);
457 $this->assertIsString($name);
460 $this->assertSame('System', context_helper::get_level_name(CONTEXT_SYSTEM));
461 $this->assertSame('User', context_helper::get_level_name(CONTEXT_USER));
462 $this->assertSame('Category', context_helper::get_level_name(CONTEXT_COURSECAT));
463 $this->assertSame('Course', context_helper::get_level_name(CONTEXT_COURSE));
464 $this->assertSame('Activity module', context_helper::get_level_name(CONTEXT_MODULE));
465 $this->assertSame('Block', context_helper::get_level_name(CONTEXT_BLOCK));
469 * Tests covered method.
470 * @covers ::get_navigation_filter_context
472 public function test_get_navigation_filter_context() {
473 global $CFG;
474 $this->resetAfterTest();
476 $user = $this->getDataGenerator()->create_user();
477 $usercontext = context\user::instance($user->id);
478 $category = $this->getDataGenerator()->create_category();
479 $categorycontext = context\coursecat::instance($category->id);
480 $course = $this->getDataGenerator()->create_course();
481 $coursecontext = context\course::instance($course->id);
482 $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
483 $pagecontext = context\module::instance($page->cmid);
484 $systemcontext = context\system::instance();
486 // Default is OFF.
487 $this->assertSame('0', $CFG->filternavigationwithsystemcontext);
489 // First test passed values are returned if disabled.
490 set_config('filternavigationwithsystemcontext', '0');
492 $this->assertNull(context_helper::get_navigation_filter_context(null));
494 $filtercontext = context_helper::get_navigation_filter_context($systemcontext);
495 $this->assertSame($systemcontext, $filtercontext);
497 $filtercontext = context_helper::get_navigation_filter_context($usercontext);
498 $this->assertSame($usercontext, $filtercontext);
500 $filtercontext = context_helper::get_navigation_filter_context($categorycontext);
501 $this->assertSame($categorycontext, $filtercontext);
503 $filtercontext = context_helper::get_navigation_filter_context($coursecontext);
504 $this->assertSame($coursecontext, $filtercontext);
506 $filtercontext = context_helper::get_navigation_filter_context($pagecontext);
507 $this->assertSame($pagecontext, $filtercontext);
509 // Now test that any input returns system context if enabled.
510 set_config('filternavigationwithsystemcontext', '1');
512 $filtercontext = context_helper::get_navigation_filter_context(null);
513 $this->assertSame($systemcontext->id, $filtercontext->id);
515 $filtercontext = context_helper::get_navigation_filter_context($systemcontext);
516 $this->assertSame($systemcontext->id, $filtercontext->id);
518 $filtercontext = context_helper::get_navigation_filter_context($usercontext);
519 $this->assertSame($systemcontext->id, $filtercontext->id);
521 $filtercontext = context_helper::get_navigation_filter_context($categorycontext);
522 $this->assertSame($systemcontext->id, $filtercontext->id);
524 $filtercontext = context_helper::get_navigation_filter_context($coursecontext);
525 $this->assertSame($systemcontext->id, $filtercontext->id);
527 $filtercontext = context_helper::get_navigation_filter_context($pagecontext);
528 $this->assertSame($systemcontext->id, $filtercontext->id);