mirror of
https://github.com/moodle/moodle.git
synced 2025-02-21 18:08:02 +01:00
Avoids removing the section breadcrumb nodes in the course module context when the course uses the 'One section per page' layout. Additionaly, it also removes the Courses and Category breadcrumb nodes in the module contexts to be consistent with the way the breadcrumbs are displayed in the course context.
547 lines
21 KiB
PHP
547 lines
21 KiB
PHP
<?php
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
namespace theme_boost;
|
|
|
|
/**
|
|
* Test the boostnavbar file
|
|
*
|
|
* @package theme_boost
|
|
* @covers \theme_boost\boostnavbar
|
|
* @copyright 2021 Peter Dias
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class boostnavbar_test extends \advanced_testcase {
|
|
/**
|
|
* Provider for test_remove_no_link_items
|
|
* The setup and expected arrays are defined as an array of 'nodekey' => $hasaction
|
|
*
|
|
* @return array
|
|
*/
|
|
public function remove_no_link_items_provider(): array {
|
|
return [
|
|
'All nodes have links links including leaf node. Set to remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => true, 'issection' => false],
|
|
'node2' => ['hasaction' => true, 'issection' => false],
|
|
'node3' => ['hasaction' => true, 'issection' => false],
|
|
],
|
|
true,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node1' => true,
|
|
'node2' => true,
|
|
'node3' => true,
|
|
]
|
|
],
|
|
'Only some parent nodes have links. Leaf node has a link. Set to remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => false, 'issection' => false],
|
|
'node2' => ['hasaction' => true, 'issection' => false],
|
|
'node3' => ['hasaction' => true, 'issection' => false],
|
|
],
|
|
true,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node2' => true,
|
|
'node3' => true,
|
|
]
|
|
],
|
|
'All parent nodes do not have links. Leaf node has a link. Set to remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => false, 'issection' => false],
|
|
'node2' => ['hasaction' => false, 'issection' => false],
|
|
'node3' => ['hasaction' => true, 'issection' => false],
|
|
],
|
|
true,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node3' => true,
|
|
]
|
|
],
|
|
'All parent nodes have links. Leaf node does not has a link. Set to remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => true, 'issection' => false],
|
|
'node2' => ['hasaction' => true, 'issection' => false],
|
|
'node3' => ['hasaction' => false, 'issection' => false],
|
|
],
|
|
true,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node1' => true,
|
|
'node2' => true,
|
|
'node3' => false,
|
|
]
|
|
],
|
|
'All parent nodes do not have links. Leaf node does not has a link. Set to remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => false, 'issection' => false],
|
|
'node2' => ['hasaction' => false, 'issection' => false],
|
|
'node3' => ['hasaction' => false, 'issection' => false],
|
|
],
|
|
true,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node3' => false,
|
|
]
|
|
],
|
|
'Some parent nodes do not have links. Leaf node does not has a link. Set to remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => true, 'issection' => false],
|
|
'node2' => ['hasaction' => false, 'issection' => false],
|
|
'node3' => ['hasaction' => false, 'issection' => false],
|
|
],
|
|
true,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node1' => true,
|
|
'node3' => false,
|
|
]
|
|
],
|
|
'All nodes have links links including leaf node and section nodes. Set to remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => true, 'issection' => false],
|
|
'node2' => ['hasaction' => true, 'issection' => false],
|
|
'sectionnode1' => ['hasaction' => true, 'issection' => true],
|
|
'node3' => ['hasaction' => true, 'issection' => false],
|
|
],
|
|
true,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node1' => true,
|
|
'node2' => true,
|
|
'node3' => true,
|
|
]
|
|
],
|
|
'All nodes have links links including leaf node and section nodes. Set to not remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => true, 'issection' => false],
|
|
'node2' => ['hasaction' => true, 'issection' => false],
|
|
'sectionnode1' => ['hasaction' => true, 'issection' => true],
|
|
'node3' => ['hasaction' => true, 'issection' => false],
|
|
],
|
|
false,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node1' => true,
|
|
'node2' => true,
|
|
'sectionnode1' => true,
|
|
'node3' => true,
|
|
]
|
|
],
|
|
'Only some parent nodes have links. Section node does not have a link. Set to not remove section nodes.' => [
|
|
[
|
|
'node1' => ['hasaction' => false, 'issection' => false],
|
|
'node2' => ['hasaction' => true, 'issection' => false],
|
|
'sectionnode1' => ['hasaction' => false, 'issection' => true],
|
|
'node3' => ['hasaction' => true, 'issection' => false],
|
|
],
|
|
true,
|
|
[
|
|
'Home' => true,
|
|
'Courses' => true,
|
|
'tc_1' => true,
|
|
'node2' => true,
|
|
'node3' => true,
|
|
]
|
|
]
|
|
];
|
|
}
|
|
/**
|
|
* Test the remove_no_link_items function
|
|
*
|
|
* @dataProvider remove_no_link_items_provider
|
|
* @param array $setup
|
|
* @param bool $removesectionnodes Whether to remove the section nodes with an associated action.
|
|
* @param array $expected
|
|
* @throws \ReflectionException
|
|
*/
|
|
public function test_remove_no_link_items(array $setup, bool $removesectionnodes, array $expected) {
|
|
global $PAGE;
|
|
|
|
$this->resetAfterTest();
|
|
// Unfortunate hack needed because people use global $PAGE around the place.
|
|
$PAGE->set_url('/');
|
|
$course = $this->getDataGenerator()->create_course();
|
|
$page = new \moodle_page();
|
|
$page->set_course($course);
|
|
$page->set_url(new \moodle_url('/course/view.php', array('id' => $course->id)));
|
|
// A dummy url to use. We don't care where it's pointing to.
|
|
$url = new \moodle_url('/');
|
|
foreach ($setup as $key => $value) {
|
|
$page->navbar->add($key, $value['hasaction'] ? $url : null,
|
|
$value['issection'] ? \navigation_node::TYPE_SECTION : null);
|
|
}
|
|
|
|
$boostnavbar = $this->getMockBuilder(boostnavbar::class)
|
|
->disableOriginalConstructor()
|
|
->onlyMethods([])
|
|
->getMock();
|
|
|
|
$rc = new \ReflectionClass(boostnavbar::class);
|
|
$rcp = $rc->getProperty('items');
|
|
$rcp->setAccessible(true);
|
|
$rcp->setValue($boostnavbar, $page->navbar->get_items());
|
|
|
|
// Make the call to the function.
|
|
$rcm = $rc->getMethod('remove_no_link_items');
|
|
$rcm->setAccessible(true);
|
|
$rcm->invoke($boostnavbar, $removesectionnodes);
|
|
|
|
// Get the value for the class variable that the function modifies.
|
|
$values = $rcp->getValue($boostnavbar);
|
|
$actual = [];
|
|
foreach ($values as $value) {
|
|
$actual[$value->text] = $value->has_action();
|
|
}
|
|
$this->assertEquals($expected, $actual);
|
|
}
|
|
|
|
/**
|
|
* Provider for test_remove_duplicate_items.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function remove_duplicate_items_provider(): array {
|
|
global $CFG;
|
|
|
|
return [
|
|
'Breadcrumb items with identical text and action url (actions of same type moodle_url).' => [
|
|
[
|
|
[
|
|
'text' => 'Node 1',
|
|
'action' => new \moodle_url('/page1.php')
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 4',
|
|
'action' => new \moodle_url('/page4.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 1])
|
|
],
|
|
],
|
|
['Home', 'Node 1', 'Node 4', 'Node 2']
|
|
],
|
|
'Breadcrumb items with identical text and action url (actions of different type moodle_url/text).' => [
|
|
[
|
|
[
|
|
'text' => 'Node 1',
|
|
'action' => new \moodle_url('/page1.php')
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 4',
|
|
'action' => new \moodle_url('/page4.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => "{$CFG->wwwroot}/page2.php?id=1"
|
|
],
|
|
],
|
|
['Home', 'Node 1', 'Node 4', 'Node 2']
|
|
],
|
|
'Breadcrumb items with identical text and action url (actions of different type moodle_url/action_link).' => [
|
|
[
|
|
[
|
|
'text' => 'Node 1',
|
|
'action' => new \moodle_url('/page1.php')
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 4',
|
|
'action' => new \moodle_url('/page4.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \action_link(new \moodle_url('/page2.php', ['id' => 1]), 'Action link')
|
|
],
|
|
],
|
|
['Home', 'Node 1', 'Node 4', 'Node 2']
|
|
],
|
|
'Breadcrumbs items with identical text but not identical action url.' => [
|
|
[
|
|
[
|
|
'text' => 'Node 1',
|
|
'action' => new \moodle_url('/page1.php')
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 2])
|
|
],
|
|
[
|
|
'text' => 'Node 4',
|
|
'action' => new \moodle_url('/page4.php', ['id' => 1])
|
|
],
|
|
],
|
|
['Home', 'Node 1', 'Node 2', 'Node 2', 'Node 4']
|
|
],
|
|
'Breadcrumb items with identical action url but not identical text.' => [
|
|
[
|
|
[
|
|
'text' => 'Node 1',
|
|
'action' => new \moodle_url('/page1.php')
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 3',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 4',
|
|
'action' => new \moodle_url('/page4.php', ['id' => 1])
|
|
],
|
|
],
|
|
['Home', 'Node 1', 'Node 2', 'Node 3', 'Node 4']
|
|
],
|
|
'Breadcrumb items without any identical action url or text.' => [
|
|
[
|
|
[
|
|
'text' => 'Node 1',
|
|
'action' => new \moodle_url('/page1.php')
|
|
],
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 3',
|
|
'action' => new \moodle_url('/page3.php', ['id' => 1])
|
|
],
|
|
[
|
|
'text' => 'Node 4',
|
|
'action' => new \moodle_url('/page4.php', ['id' => 1])
|
|
],
|
|
],
|
|
['Home', 'Node 1', 'Node 2', 'Node 3', 'Node 4']
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Test the remove_duplicate_items function.
|
|
*
|
|
* @dataProvider remove_duplicate_items_provider
|
|
* @param array $navbarnodes The array containing the text and action of the nodes to be added to the navbar
|
|
* @param array $expected The array containing the text of the expected navbar nodes
|
|
*/
|
|
public function test_remove_duplicate_items(array $navbarnodes, array $expected) {
|
|
$this->resetAfterTest();
|
|
$page = new \moodle_page();
|
|
$page->set_url('/');
|
|
|
|
// Add the navbar nodes.
|
|
foreach ($navbarnodes as $node) {
|
|
$page->navbar->add($node['text'], $node['action'], \navigation_node::TYPE_CUSTOM);
|
|
}
|
|
|
|
$boostnavbar = $this->getMockBuilder(boostnavbar::class)
|
|
->disableOriginalConstructor()
|
|
->onlyMethods([])
|
|
->getMock();
|
|
|
|
$rc = new \ReflectionClass(boostnavbar::class);
|
|
$rcp = $rc->getProperty('items');
|
|
$rcp->setAccessible(true);
|
|
$rcp->setValue($boostnavbar, $page->navbar->get_items());
|
|
|
|
// Make the call to the function.
|
|
$rcm = $rc->getMethod('remove_duplicate_items');
|
|
$rcm->setAccessible(true);
|
|
$rcm->invoke($boostnavbar);
|
|
|
|
// Get the value for the class variable that the function modifies.
|
|
$values = $rcp->getValue($boostnavbar);
|
|
$actual = [];
|
|
foreach ($values as $value) {
|
|
$actual[] = $value->text;
|
|
}
|
|
$this->assertEquals($expected, $actual);
|
|
}
|
|
|
|
|
|
/**
|
|
* Provider for test_remove_items_that_exist_in_navigation.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function remove_items_that_exist_in_navigation_provider(): array {
|
|
global $CFG;
|
|
|
|
return [
|
|
'Item with identical action url and text exists in the primary navigation menu.' => [
|
|
'primary',
|
|
[
|
|
[
|
|
'text' => 'Node 1',
|
|
'action' => new \moodle_url('/page1.php')
|
|
],
|
|
],
|
|
[
|
|
'Node 1' => new \moodle_url('/page1.php'),
|
|
'Node 2' => new \moodle_url('/page2.php'),
|
|
'Node 3' => new \moodle_url('/page1.php'),
|
|
],
|
|
['Node 2', 'Node 3']
|
|
],
|
|
'Item with identical action url and text exists in the secondary navigation menu.' => [
|
|
'secondary',
|
|
[
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php')
|
|
],
|
|
],
|
|
[
|
|
'Node 1' => new \moodle_url('/page1.php'),
|
|
'Node 2' => new \moodle_url('/page2.php'),
|
|
'Node 3' => new \moodle_url('/page1.php'),
|
|
],
|
|
['Home', 'Node 1', 'Node 3']
|
|
],
|
|
'Multiple items with identical action url and text exist in the secondary navigation menu.' => [
|
|
'secondary',
|
|
[
|
|
[
|
|
'text' => 'Node 2',
|
|
'action' => new \moodle_url('/page2.php')
|
|
],
|
|
[
|
|
'text' => 'Node 3',
|
|
'action' => new \moodle_url('/page3.php')
|
|
],
|
|
],
|
|
[
|
|
'Node 1' => new \moodle_url('/page1.php'),
|
|
'Node 2' => "{$CFG->wwwroot}/page2.php",
|
|
'Node 3' => new \action_link(new \moodle_url('/page3.php'), 'Action link'),
|
|
],
|
|
['Home', 'Node 1']
|
|
],
|
|
'No items with identical action url and text in the secondary navigation menu.' => [
|
|
'secondary',
|
|
[
|
|
[
|
|
'text' => 'Node 4',
|
|
'action' => new \moodle_url('/page4.php')
|
|
],
|
|
],
|
|
[
|
|
'Node 1' => new \moodle_url('/page1.php'),
|
|
'Node 2' => new \moodle_url('/page2.php'),
|
|
'Node 3' => new \moodle_url('/page1.php'),
|
|
],
|
|
['Home', 'Node 1', 'Node 2', 'Node 3']
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Test the remove_items_that_exist_in_navigation function.
|
|
*
|
|
* @dataProvider remove_items_that_exist_in_navigation_provider
|
|
* @param string $navmenu The name of the navigation menu we would like to use (primary or secondary)
|
|
* @param array $navmenunodes The array containing the text and action of the nodes to be added to the navigation menu
|
|
* @param array $navbarnodes Array containing the text => action of the nodes to be added to the navbar
|
|
* @param array $expected Array containing the text of the expected navbar nodes after the filtering
|
|
*/
|
|
public function test_remove_items_that_exist_in_navigation(string $navmenu, array $navmenunodes, array $navbarnodes,
|
|
array $expected) {
|
|
global $PAGE;
|
|
|
|
// Unfortunate hack needed because people use global $PAGE around the place.
|
|
$PAGE->set_url('/');
|
|
$this->resetAfterTest();
|
|
$page = new \moodle_page();
|
|
$page->set_url('/');
|
|
|
|
switch ($navmenu) {
|
|
case 'primary':
|
|
$navigationmenu = new \core\navigation\views\primary($page);
|
|
break;
|
|
case 'secondary':
|
|
$navigationmenu = new \core\navigation\views\secondary($page);
|
|
}
|
|
|
|
$navigationmenu->initialise();
|
|
// Add the additional nodes to the navigation menu.
|
|
foreach ($navmenunodes as $navmenunode) {
|
|
$navigationmenu->add($navmenunode['text'], $navmenunode['action'], \navigation_node::TYPE_CUSTOM);
|
|
}
|
|
|
|
// Add the additional navbar nodes.
|
|
foreach ($navbarnodes as $text => $action) {
|
|
$page->navbar->add($text, $action, \navigation_node::TYPE_CUSTOM);
|
|
}
|
|
|
|
$boostnavbar = $this->getMockBuilder(boostnavbar::class)
|
|
->disableOriginalConstructor()
|
|
->onlyMethods([])
|
|
->getMock();
|
|
|
|
$rc = new \ReflectionClass(boostnavbar::class);
|
|
$rcp = $rc->getProperty('items');
|
|
$rcp->setAccessible(true);
|
|
$rcp->setValue($boostnavbar, $page->navbar->get_items());
|
|
|
|
// Make the call to the function.
|
|
$rcm = $rc->getMethod('remove_items_that_exist_in_navigation');
|
|
$rcm->setAccessible(true);
|
|
$rcm->invoke($boostnavbar, $navigationmenu);
|
|
|
|
// Get the value for the class variable that the function modifies.
|
|
$values = $rcp->getValue($boostnavbar);
|
|
$actual = [];
|
|
foreach ($values as $value) {
|
|
$actual[] = $value->text;
|
|
}
|
|
$this->assertEquals($expected, $actual);
|
|
}
|
|
}
|