2 // This file is part of Moodle - http://moodle.org/
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.
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 <http://www.gnu.org/licenses/>.
17 namespace core_search
;
19 use advanced_testcase
;
21 use core_mocksearch\search\mock_search_area
;
22 use mock_search\engine
;
23 use testable_core_search
;
27 * Unit tests for search document.
29 * @package core_search
31 * @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 * @coversDefaultClass \core_search\document
35 class document_test
extends \advanced_testcase
{
38 * Setup to ensure that fixtures are loaded.
40 public static function setupBeforeClass(): void
{
42 require_once($CFG->dirroot
. '/search/tests/fixtures/testable_core_search.php');
43 require_once($CFG->dirroot
. '/search/tests/fixtures/mock_search_area.php');
47 * @var Instace of core_search_generator.
49 protected $generator = null;
51 public function setUp(): void
{
52 $this->resetAfterTest();
53 set_config('enableglobalsearch', true);
55 // Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
56 $search = \testable_core_search
::instance();
58 $this->generator
= self
::getDataGenerator()->get_plugin_generator('core_search');
59 $this->generator
->setup();
63 * Adding this test here as get_areas_user_accesses process is the same, results just depend on the context level.
65 * @covers ::export_for_template
68 public function test_search_user_accesses() {
71 $area = new mock_search_area();
72 $renderer = $PAGE->get_renderer('core_search');
73 $engine = new engine();
75 $course = $this->getDataGenerator()->create_course(['fullname' => 'Course & Title']);
76 $user = $this->getDataGenerator()->create_user(['firstname' => 'User', 'lastname' => 'Escape & Name']);
77 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, 'teacher');
78 $this->setAdminUser();
80 // Make a record to enter in the search area.
81 $record = new stdClass();
82 $record->title
= 'Escape & Title';
83 $record->content
= 'Escape & Content';
84 $record->description1
= 'Escape & Description1';
85 $record->description2
= 'Escape & Description2';
86 $record->userid
= $user->id
;
87 $record->courseid
= $course->id
;
88 $record = $this->generator
->create_record($record);
90 // Convert to a 'doc data' type format.
91 $docdata = $area->convert_record_to_doc_array($record);
93 // First see that the docuemnt has the right information, unescaped.
94 $doc = $engine->to_document($area, $docdata);
95 $this->assertEquals('Escape & Title', $doc->get('title'));
96 $this->assertEquals('Escape & Content', $doc->get('content'));
97 $this->assertEquals('Escape & Description1', $doc->get('description1'));
98 $this->assertEquals('Escape & Description2', $doc->get('description2'));
99 $this->assertEquals('User Escape & Name', $doc->get('userfullname'));
100 $this->assertEquals('Course & Title', $doc->get('coursefullname'));
102 // Export for template, and see if it is escaped.
103 $export = $doc->export_for_template($renderer);
104 $this->assertEquals('Escape & Title', $export['title']);
105 $this->assertEquals('Escape & Content', $export['content']);
106 $this->assertEquals('Escape & Description1', $export['description1']);
107 $this->assertEquals('Escape & Description2', $export['description2']);
108 $this->assertEquals('User Escape & Name', $export['userfullname']);
109 $this->assertEquals('Course & Title', $export['coursefullname']);
113 * Test we can set and get document icon.
115 * @covers ::set_doc_icon
117 public function test_get_and_set_doc_icon() {
118 $document = $this->getMockBuilder('\core_search\document')
119 ->disableOriginalConstructor()
120 ->getMockForAbstractClass();
122 $this->assertNull($document->get_doc_icon());
124 $docicon = new \core_search\
document_icon('test_name', 'test_component');
125 $document->set_doc_icon($docicon);
127 $this->assertEquals($docicon, $document->get_doc_icon());
130 public function tearDown(): void
{
131 // For unit tests before PHP 7, teardown is called even on skip. So only do our teardown if we did setup.
132 if ($this->generator
) {
133 // Moodle DML freaks out if we don't teardown the temp table after each run.
134 $this->generator
->teardown();
135 $this->generator
= null;
140 * Test the document author visibility depending on the user capabilities.
142 * @covers ::export_for_template
143 * @dataProvider document_author_visibility_provider
144 * @param string $rolename the role name
145 * @param array $capexceptions the capabilities exceptions
146 * @param bool $expected the expected author visibility
147 * @param bool $owndocument if the resulting document belongs to the current user
149 public function test_document_author_visibility(
150 string $rolename = 'editingteacher',
151 array $capexceptions = [],
152 bool $expected = true,
153 bool $owndocument = false
157 $area = new mock_search_area();
158 $renderer = $PAGE->get_renderer('core_search');
159 $engine = new engine();
161 $course = $this->getDataGenerator()->create_course(['fullname' => 'Course & Title']);
162 $context = context_course
::instance($course->id
);
164 $roleid = $DB->get_field('role', 'id', ['shortname' => $rolename]);
165 foreach ($capexceptions as $capability) {
166 assign_capability($capability, CAP_PROHIBIT
, $roleid, $context->id
);
169 $user = $this->getDataGenerator()->create_user(['firstname' => 'Test', 'lastname' => 'User']);
170 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $rolename);
171 $this->setUser($user);
176 $author = $this->getDataGenerator()->create_user(['firstname' => 'User', 'lastname' => 'Escape & Name']);
177 $this->getDataGenerator()->enrol_user($author->id
, $course->id
, 'student');
180 // Make a record to enter in the search area.
181 $record = new stdClass();
182 $record->title
= 'Escape & Title';
183 $record->content
= 'Escape & Content';
184 $record->description1
= 'Escape & Description1';
185 $record->description2
= 'Escape & Description2';
186 $record->userid
= $author->id
;
187 $record->courseid
= $course->id
;
188 $record->contextid
= $context->id
;
189 $record = $this->generator
->create_record($record);
191 // Convert to a 'doc data' type format.
192 $docdata = $area->convert_record_to_doc_array($record);
194 // First see that the document has the user information.
195 $doc = $engine->to_document($area, $docdata);
196 $this->assertEquals(fullname($author), $doc->get('userfullname'));
198 // Export for template, and see if it the user information is exported.
199 $export = $doc->export_for_template($renderer);
202 $authorname = htmlentities(fullname($author));
203 $this->assertEquals($authorname, $export['userfullname']);
205 $this->assertArrayNotHasKey('userfullname', $export);
210 * Data provider for test_document_author_visibility().
214 public function document_author_visibility_provider(): array {
217 'rolename' => 'editingteacher',
218 'capexceptions' => [],
220 'owndocument' => false,
222 'Non editing teacher' => [
223 'rolename' => 'teacher',
224 'capexceptions' => [],
226 'owndocument' => false,
229 'rolename' => 'student',
230 'capexceptions' => [],
232 'owndocument' => false,
234 // Adding capability exceptions.
235 'Student without view profiles' => [
236 'rolename' => 'student',
237 'capexceptions' => ['moodle/user:viewdetails'],
239 'owndocument' => false,
241 'Student without view participants' => [
242 'rolename' => 'student',
243 'capexceptions' => ['moodle/course:viewparticipants'],
245 'owndocument' => false,
247 'Student without view participants or profiles' => [
248 'rolename' => 'student',
249 'capexceptions' => ['moodle/user:viewdetails', 'moodle/course:viewparticipants'],
251 'owndocument' => false,
253 // Users should be able to see its own documents.
254 'Student author without view profiles' => [
255 'rolename' => 'student',
256 'capexceptions' => ['moodle/user:viewdetails'],
258 'owndocument' => true,
260 'Student author without view participants' => [
261 'rolename' => 'student',
262 'capexceptions' => ['moodle/course:viewparticipants'],
264 'owndocument' => true,
266 'Student author without view participants or profiles' => [
267 'rolename' => 'student',
268 'capexceptions' => ['moodle/user:viewdetails', 'moodle/course:viewparticipants'],
270 'owndocument' => true,