See Release Notes
Long Term Support Release
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace theme_boost; 18 19 /** 20 * Test the boostnavbar file 21 * 22 * @package theme_boost 23 * @covers \theme_boost\boostnavbar 24 * @copyright 2021 Peter Dias 25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 */ 27 class boostnavbar_test extends \advanced_testcase { 28 /** 29 * Provider for test_remove_no_link_items 30 * The setup and expected arrays are defined as an array of 'nodekey' => $hasaction 31 * 32 * @return array 33 */ 34 public function remove_no_link_items_provider(): array { 35 return [ 36 'All nodes have links links including leaf node. Set to remove section nodes.' => [ 37 [ 38 'node1' => ['hasaction' => true, 'issection' => false], 39 'node2' => ['hasaction' => true, 'issection' => false], 40 'node3' => ['hasaction' => true, 'issection' => false], 41 ], 42 true, 43 [ 44 'Home' => true, 45 'Courses' => true, 46 'tc_1' => true, 47 'node1' => true, 48 'node2' => true, 49 'node3' => true, 50 ] 51 ], 52 'Only some parent nodes have links. Leaf node has a link. Set to remove section nodes.' => [ 53 [ 54 'node1' => ['hasaction' => false, 'issection' => false], 55 'node2' => ['hasaction' => true, 'issection' => false], 56 'node3' => ['hasaction' => true, 'issection' => false], 57 ], 58 true, 59 [ 60 'Home' => true, 61 'Courses' => true, 62 'tc_1' => true, 63 'node2' => true, 64 'node3' => true, 65 ] 66 ], 67 'All parent nodes do not have links. Leaf node has a link. Set to remove section nodes.' => [ 68 [ 69 'node1' => ['hasaction' => false, 'issection' => false], 70 'node2' => ['hasaction' => false, 'issection' => false], 71 'node3' => ['hasaction' => true, 'issection' => false], 72 ], 73 true, 74 [ 75 'Home' => true, 76 'Courses' => true, 77 'tc_1' => true, 78 'node3' => true, 79 ] 80 ], 81 'All parent nodes have links. Leaf node does not has a link. Set to remove section nodes.' => [ 82 [ 83 'node1' => ['hasaction' => true, 'issection' => false], 84 'node2' => ['hasaction' => true, 'issection' => false], 85 'node3' => ['hasaction' => false, 'issection' => false], 86 ], 87 true, 88 [ 89 'Home' => true, 90 'Courses' => true, 91 'tc_1' => true, 92 'node1' => true, 93 'node2' => true, 94 'node3' => false, 95 ] 96 ], 97 'All parent nodes do not have links. Leaf node does not has a link. Set to remove section nodes.' => [ 98 [ 99 'node1' => ['hasaction' => false, 'issection' => false], 100 'node2' => ['hasaction' => false, 'issection' => false], 101 'node3' => ['hasaction' => false, 'issection' => false], 102 ], 103 true, 104 [ 105 'Home' => true, 106 'Courses' => true, 107 'tc_1' => true, 108 'node3' => false, 109 ] 110 ], 111 'Some parent nodes do not have links. Leaf node does not has a link. Set to remove section nodes.' => [ 112 [ 113 'node1' => ['hasaction' => true, 'issection' => false], 114 'node2' => ['hasaction' => false, 'issection' => false], 115 'node3' => ['hasaction' => false, 'issection' => false], 116 ], 117 true, 118 [ 119 'Home' => true, 120 'Courses' => true, 121 'tc_1' => true, 122 'node1' => true, 123 'node3' => false, 124 ] 125 ], 126 'All nodes have links links including leaf node and section nodes. Set to remove section nodes.' => [ 127 [ 128 'node1' => ['hasaction' => true, 'issection' => false], 129 'node2' => ['hasaction' => true, 'issection' => false], 130 'sectionnode1' => ['hasaction' => true, 'issection' => true], 131 'node3' => ['hasaction' => true, 'issection' => false], 132 ], 133 true, 134 [ 135 'Home' => true, 136 'Courses' => true, 137 'tc_1' => true, 138 'node1' => true, 139 'node2' => true, 140 'node3' => true, 141 ] 142 ], 143 'All nodes have links links including leaf node and section nodes. Set to not remove section nodes.' => [ 144 [ 145 'node1' => ['hasaction' => true, 'issection' => false], 146 'node2' => ['hasaction' => true, 'issection' => false], 147 'sectionnode1' => ['hasaction' => true, 'issection' => true], 148 'node3' => ['hasaction' => true, 'issection' => false], 149 ], 150 false, 151 [ 152 'Home' => true, 153 'Courses' => true, 154 'tc_1' => true, 155 'node1' => true, 156 'node2' => true, 157 'sectionnode1' => true, 158 'node3' => true, 159 ] 160 ], 161 'Only some parent nodes have links. Section node does not have a link. Set to not remove section nodes.' => [ 162 [ 163 'node1' => ['hasaction' => false, 'issection' => false], 164 'node2' => ['hasaction' => true, 'issection' => false], 165 'sectionnode1' => ['hasaction' => false, 'issection' => true], 166 'node3' => ['hasaction' => true, 'issection' => false], 167 ], 168 true, 169 [ 170 'Home' => true, 171 'Courses' => true, 172 'tc_1' => true, 173 'node2' => true, 174 'node3' => true, 175 ] 176 ] 177 ]; 178 } 179 /** 180 * Test the remove_no_link_items function 181 * 182 * @dataProvider remove_no_link_items_provider 183 * @param array $setup 184 * @param bool $removesectionnodes Whether to remove the section nodes with an associated action. 185 * @param array $expected 186 * @throws \ReflectionException 187 */ 188 public function test_remove_no_link_items(array $setup, bool $removesectionnodes, array $expected) { 189 global $PAGE; 190 191 $this->resetAfterTest(); 192 // Unfortunate hack needed because people use global $PAGE around the place. 193 $PAGE->set_url('/'); 194 $course = $this->getDataGenerator()->create_course(); 195 $page = new \moodle_page(); 196 $page->set_course($course); 197 $page->set_url(new \moodle_url('/course/view.php', array('id' => $course->id))); 198 // A dummy url to use. We don't care where it's pointing to. 199 $url = new \moodle_url('/'); 200 foreach ($setup as $key => $value) { 201 $page->navbar->add($key, $value['hasaction'] ? $url : null, 202 $value['issection'] ? \navigation_node::TYPE_SECTION : null); 203 } 204 205 $boostnavbar = $this->getMockBuilder(boostnavbar::class) 206 ->disableOriginalConstructor() 207 ->onlyMethods([]) 208 ->getMock(); 209 210 $rc = new \ReflectionClass(boostnavbar::class); 211 $rcp = $rc->getProperty('items'); 212 $rcp->setAccessible(true); 213 $rcp->setValue($boostnavbar, $page->navbar->get_items()); 214 215 // Make the call to the function. 216 $rcm = $rc->getMethod('remove_no_link_items'); 217 $rcm->setAccessible(true); 218 $rcm->invoke($boostnavbar, $removesectionnodes); 219 220 // Get the value for the class variable that the function modifies. 221 $values = $rcp->getValue($boostnavbar); 222 $actual = []; 223 foreach ($values as $value) { 224 $actual[$value->text] = $value->has_action(); 225 } 226 $this->assertEquals($expected, $actual); 227 } 228 229 /** 230 * Provider for test_remove_duplicate_items. 231 * 232 * @return array 233 */ 234 public function remove_duplicate_items_provider(): array { 235 global $CFG; 236 237 return [ 238 'Breadcrumb items with identical text and action url (actions of same type moodle_url).' => [ 239 [ 240 [ 241 'text' => 'Node 1', 242 'action' => new \moodle_url('/page1.php') 243 ], 244 [ 245 'text' => 'Node 2', 246 'action' => new \moodle_url('/page2.php', ['id' => 1]) 247 ], 248 [ 249 'text' => 'Node 4', 250 'action' => new \moodle_url('/page4.php', ['id' => 1]) 251 ], 252 [ 253 'text' => 'Node 2', 254 'action' => new \moodle_url('/page2.php', ['id' => 1]) 255 ], 256 ], 257 ['Home', 'Node 1', 'Node 4', 'Node 2'] 258 ], 259 'Breadcrumb items with identical text and action url (actions of different type moodle_url/text).' => [ 260 [ 261 [ 262 'text' => 'Node 1', 263 'action' => new \moodle_url('/page1.php') 264 ], 265 [ 266 'text' => 'Node 2', 267 'action' => new \moodle_url('/page2.php', ['id' => 1]) 268 ], 269 [ 270 'text' => 'Node 4', 271 'action' => new \moodle_url('/page4.php', ['id' => 1]) 272 ], 273 [ 274 'text' => 'Node 2', 275 'action' => "{$CFG->wwwroot}/page2.php?id=1" 276 ], 277 ], 278 ['Home', 'Node 1', 'Node 4', 'Node 2'] 279 ], 280 'Breadcrumb items with identical text and action url (actions of different type moodle_url/action_link).' => [ 281 [ 282 [ 283 'text' => 'Node 1', 284 'action' => new \moodle_url('/page1.php') 285 ], 286 [ 287 'text' => 'Node 2', 288 'action' => new \moodle_url('/page2.php', ['id' => 1]) 289 ], 290 [ 291 'text' => 'Node 4', 292 'action' => new \moodle_url('/page4.php', ['id' => 1]) 293 ], 294 [ 295 'text' => 'Node 2', 296 'action' => new \action_link(new \moodle_url('/page2.php', ['id' => 1]), 'Action link') 297 ], 298 ], 299 ['Home', 'Node 1', 'Node 4', 'Node 2'] 300 ], 301 'Breadcrumbs items with identical text but not identical action url.' => [ 302 [ 303 [ 304 'text' => 'Node 1', 305 'action' => new \moodle_url('/page1.php') 306 ], 307 [ 308 'text' => 'Node 2', 309 'action' => new \moodle_url('/page2.php', ['id' => 1]) 310 ], 311 [ 312 'text' => 'Node 2', 313 'action' => new \moodle_url('/page2.php', ['id' => 2]) 314 ], 315 [ 316 'text' => 'Node 4', 317 'action' => new \moodle_url('/page4.php', ['id' => 1]) 318 ], 319 ], 320 ['Home', 'Node 1', 'Node 2', 'Node 2', 'Node 4'] 321 ], 322 'Breadcrumb items with identical action url but not identical text.' => [ 323 [ 324 [ 325 'text' => 'Node 1', 326 'action' => new \moodle_url('/page1.php') 327 ], 328 [ 329 'text' => 'Node 2', 330 'action' => new \moodle_url('/page2.php', ['id' => 1]) 331 ], 332 [ 333 'text' => 'Node 3', 334 'action' => new \moodle_url('/page2.php', ['id' => 1]) 335 ], 336 [ 337 'text' => 'Node 4', 338 'action' => new \moodle_url('/page4.php', ['id' => 1]) 339 ], 340 ], 341 ['Home', 'Node 1', 'Node 2', 'Node 3', 'Node 4'] 342 ], 343 'Breadcrumb items without any identical action url or text.' => [ 344 [ 345 [ 346 'text' => 'Node 1', 347 'action' => new \moodle_url('/page1.php') 348 ], 349 [ 350 'text' => 'Node 2', 351 'action' => new \moodle_url('/page2.php', ['id' => 1]) 352 ], 353 [ 354 'text' => 'Node 3', 355 'action' => new \moodle_url('/page3.php', ['id' => 1]) 356 ], 357 [ 358 'text' => 'Node 4', 359 'action' => new \moodle_url('/page4.php', ['id' => 1]) 360 ], 361 ], 362 ['Home', 'Node 1', 'Node 2', 'Node 3', 'Node 4'] 363 ], 364 ]; 365 } 366 367 /** 368 * Test the remove_duplicate_items function. 369 * 370 * @dataProvider remove_duplicate_items_provider 371 * @param array $navbarnodes The array containing the text and action of the nodes to be added to the navbar 372 * @param array $expected The array containing the text of the expected navbar nodes 373 */ 374 public function test_remove_duplicate_items(array $navbarnodes, array $expected) { 375 $this->resetAfterTest(); 376 $page = new \moodle_page(); 377 $page->set_url('/'); 378 379 // Add the navbar nodes. 380 foreach ($navbarnodes as $node) { 381 $page->navbar->add($node['text'], $node['action'], \navigation_node::TYPE_CUSTOM); 382 } 383 384 $boostnavbar = $this->getMockBuilder(boostnavbar::class) 385 ->disableOriginalConstructor() 386 ->onlyMethods([]) 387 ->getMock(); 388 389 $rc = new \ReflectionClass(boostnavbar::class); 390 $rcp = $rc->getProperty('items'); 391 $rcp->setAccessible(true); 392 $rcp->setValue($boostnavbar, $page->navbar->get_items()); 393 394 // Make the call to the function. 395 $rcm = $rc->getMethod('remove_duplicate_items'); 396 $rcm->setAccessible(true); 397 $rcm->invoke($boostnavbar); 398 399 // Get the value for the class variable that the function modifies. 400 $values = $rcp->getValue($boostnavbar); 401 $actual = []; 402 foreach ($values as $value) { 403 $actual[] = $value->text; 404 } 405 $this->assertEquals($expected, $actual); 406 } 407 408 409 /** 410 * Provider for test_remove_items_that_exist_in_navigation. 411 * 412 * @return array 413 */ 414 public function remove_items_that_exist_in_navigation_provider(): array { 415 global $CFG; 416 417 return [ 418 'Item with identical action url and text exists in the primary navigation menu.' => [ 419 'primary', 420 [ 421 [ 422 'text' => 'Node 1', 423 'action' => new \moodle_url('/page1.php') 424 ], 425 ], 426 [ 427 'Node 1' => new \moodle_url('/page1.php'), 428 'Node 2' => new \moodle_url('/page2.php'), 429 'Node 3' => new \moodle_url('/page1.php'), 430 ], 431 ['Node 2', 'Node 3'] 432 ], 433 'Item with identical action url and text exists in the secondary navigation menu.' => [ 434 'secondary', 435 [ 436 [ 437 'text' => 'Node 2', 438 'action' => new \moodle_url('/page2.php') 439 ], 440 ], 441 [ 442 'Node 1' => new \moodle_url('/page1.php'), 443 'Node 2' => new \moodle_url('/page2.php'), 444 'Node 3' => new \moodle_url('/page1.php'), 445 ], 446 ['Home', 'Node 1', 'Node 3'] 447 ], 448 'Multiple items with identical action url and text exist in the secondary navigation menu.' => [ 449 'secondary', 450 [ 451 [ 452 'text' => 'Node 2', 453 'action' => new \moodle_url('/page2.php') 454 ], 455 [ 456 'text' => 'Node 3', 457 'action' => new \moodle_url('/page3.php') 458 ], 459 ], 460 [ 461 'Node 1' => new \moodle_url('/page1.php'), 462 'Node 2' => "{$CFG->wwwroot}/page2.php", 463 'Node 3' => new \action_link(new \moodle_url('/page3.php'), 'Action link'), 464 ], 465 ['Home', 'Node 1'] 466 ], 467 'No items with identical action url and text in the secondary navigation menu.' => [ 468 'secondary', 469 [ 470 [ 471 'text' => 'Node 4', 472 'action' => new \moodle_url('/page4.php') 473 ], 474 ], 475 [ 476 'Node 1' => new \moodle_url('/page1.php'), 477 'Node 2' => new \moodle_url('/page2.php'), 478 'Node 3' => new \moodle_url('/page1.php'), 479 ], 480 ['Home', 'Node 1', 'Node 2', 'Node 3'] 481 ], 482 ]; 483 } 484 485 /** 486 * Test the remove_items_that_exist_in_navigation function. 487 * 488 * @dataProvider remove_items_that_exist_in_navigation_provider 489 * @param string $navmenu The name of the navigation menu we would like to use (primary or secondary) 490 * @param array $navmenunodes The array containing the text and action of the nodes to be added to the navigation menu 491 * @param array $navbarnodes Array containing the text => action of the nodes to be added to the navbar 492 * @param array $expected Array containing the text of the expected navbar nodes after the filtering 493 */ 494 public function test_remove_items_that_exist_in_navigation(string $navmenu, array $navmenunodes, array $navbarnodes, 495 array $expected) { 496 global $PAGE; 497 498 // Unfortunate hack needed because people use global $PAGE around the place. 499 $PAGE->set_url('/'); 500 $this->resetAfterTest(); 501 $page = new \moodle_page(); 502 $page->set_url('/'); 503 504 switch ($navmenu) { 505 case 'primary': 506 $navigationmenu = new \core\navigation\views\primary($page); 507 break; 508 case 'secondary': 509 $navigationmenu = new \core\navigation\views\secondary($page); 510 } 511 512 $navigationmenu->initialise(); 513 // Add the additional nodes to the navigation menu. 514 foreach ($navmenunodes as $navmenunode) { 515 $navigationmenu->add($navmenunode['text'], $navmenunode['action'], \navigation_node::TYPE_CUSTOM); 516 } 517 518 // Add the additional navbar nodes. 519 foreach ($navbarnodes as $text => $action) { 520 $page->navbar->add($text, $action, \navigation_node::TYPE_CUSTOM); 521 } 522 523 $boostnavbar = $this->getMockBuilder(boostnavbar::class) 524 ->disableOriginalConstructor() 525 ->onlyMethods([]) 526 ->getMock(); 527 528 $rc = new \ReflectionClass(boostnavbar::class); 529 $rcp = $rc->getProperty('items'); 530 $rcp->setAccessible(true); 531 $rcp->setValue($boostnavbar, $page->navbar->get_items()); 532 533 // Make the call to the function. 534 $rcm = $rc->getMethod('remove_items_that_exist_in_navigation'); 535 $rcm->setAccessible(true); 536 $rcm->invoke($boostnavbar, $navigationmenu); 537 538 // Get the value for the class variable that the function modifies. 539 $values = $rcp->getValue($boostnavbar); 540 $actual = []; 541 foreach ($values as $value) { 542 $actual[] = $value->text; 543 } 544 $this->assertEquals($expected, $actual); 545 } 546 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body