MDL-71036 phpunit: assertContains() now performs strict comparison
[moodle.git] / contentbank / tests / privacy_test.php
blob63847d6d6500fca0f3bf7965ce9e0be1e197a49d
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.
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 * Base class for unit tests for core_contentbank.
20 * @package core_contentbank
21 * @category test
22 * @copyright 2020 Carlos Escobedo <carlos@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 namespace core_contentbank;
28 use stdClass;
29 use context_system;
30 use context_coursecat;
31 use context_course;
32 use context_user;
33 use core_contentbank\privacy\provider;
34 use core_privacy\local\request\approved_contextlist;
35 use core_privacy\local\request\writer;
36 use core_privacy\tests\provider_testcase;
37 use core_privacy\local\request\userlist;
38 use core_privacy\local\request\approved_userlist;
40 /**
41 * Unit tests for contentbank\classes\privacy\provider.php
43 * @copyright 2020 Carlos Escobedo <carlos@moodle.com>
44 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
46 class core_contentbank_privacy_testcase extends provider_testcase {
48 /**
49 * Setup to ensure that fixtures are loaded.
51 public static function setupBeforeClass(): void {
52 global $CFG;
53 require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
56 /**
57 * Test for provider::get_contexts_for_userid().
59 public function test_get_contexts_for_userid() {
61 $this->resetAfterTest();
62 // Setup scenario.
63 $scenario = $this->setup_scenario();
65 // Testing againts Manager who has content in the three contexts.
66 $contextlist = provider::get_contexts_for_userid($scenario->manager->id);
67 // There are three contexts in the list.
68 $contextlistids = $contextlist->get_contextids();
69 $this->assertCount(3, $contextlistids);
70 // Check the list against the expected list of contexts.
71 $this->assertContainsEquals($scenario->systemcontext->id, $contextlistids);
72 $this->assertContainsEquals($scenario->coursecategorycontext->id,
73 $contextlistids);
74 $this->assertContainsEquals($scenario->coursecontext->id, $contextlistids);
76 // Testing againts Teacher who has content in the one context.
77 $contextlist = provider::get_contexts_for_userid($scenario->teacher->id);
78 // There are only one context in the list.
79 $contextlistids = $contextlist->get_contextids();
80 $this->assertCount(1, $contextlistids);
81 // Check the againts Course Context.
82 $this->assertContainsEquals($scenario->coursecontext->id, $contextlistids);
83 // And there is not a System and Course Category Context.
84 $this->assertNotContainsEquals($scenario->systemcontext->id, $contextlistids);
85 $this->assertNotContainsEquals($scenario->coursecategorycontext->id, $contextlistids);
88 /**
89 * Test for provider::get_users_in_context().
91 public function test_get_users_in_context() {
93 $this->resetAfterTest();
94 // Setup scenario.
95 $scenario = $this->setup_scenario();
97 // Get the userlist to Context System, only Manager will be there.
98 $userlist = new userlist($scenario->systemcontext, 'core_contentbank');
99 provider::get_users_in_context($userlist);
100 $this->assertEquals([$scenario->manager->id], $userlist->get_userids());
101 // Teacher will not be there.
102 $this->assertNotEquals([$scenario->teacher->id], $userlist->get_userids());
104 // Get the userlist to Context Course, Manager and Teacher will be there.
105 $userlist = new userlist($scenario->coursecontext, 'core_contentbank');
106 provider::get_users_in_context($userlist);
108 $expected = [$scenario->manager->id, $scenario->teacher->id];
109 sort($expected);
110 $actual = $userlist->get_userids();
111 sort($actual);
112 $this->assertEquals($expected, $actual);
116 * Test for provider::test_export_user_data().
118 public function test_export_user_data() {
120 $this->resetAfterTest();
121 // Setup scenario.
122 $scenario = $this->setup_scenario();
124 $subcontexts = [
125 get_string('name', 'core_contentbank')
127 // Get the data for the System Context.
128 $writer = writer::with_context($scenario->systemcontext);
129 $this->assertFalse($writer->has_any_data());
130 // Export data for Manager.
131 $this->export_context_data_for_user($scenario->manager->id,
132 $scenario->systemcontext, 'core_contentbank');
133 $data = $writer->get_data($subcontexts);
134 $this->assertCount(3, (array) $data);
135 $this->assertCount(3, $writer->get_files($subcontexts));
137 // Get the data for the Course Categoy Context.
138 $writer = writer::with_context($scenario->coursecategorycontext);
139 // Export data for Manager.
140 $this->export_context_data_for_user($scenario->manager->id,
141 $scenario->coursecategorycontext, 'core_contentbank');
142 $data = $writer->get_data($subcontexts);
143 $this->assertCount(2, (array) $data);
144 $this->assertCount(2, $writer->get_files($subcontexts));
146 // Get the data for the Course Context.
147 $writer = writer::with_context($scenario->coursecontext);
148 // Export data for Manager.
149 $this->export_context_data_for_user($scenario->manager->id,
150 $scenario->coursecontext, 'core_contentbank');
151 $data = $writer->get_data($subcontexts);
152 $this->assertCount(2, (array) $data);
153 $this->assertCount(2, $writer->get_files($subcontexts));
155 // Export data for Teacher.
156 $writer = writer::reset();
157 $writer = writer::with_context($scenario->coursecontext);
158 $this->export_context_data_for_user($scenario->teacher->id,
159 $scenario->coursecontext, 'core_contentbank');
160 $data = $writer->get_data($subcontexts);
161 $this->assertCount(3, (array) $data);
162 $this->assertCount(3, $writer->get_files($subcontexts));
166 * Test for provider::delete_data_for_all_users_in_context().
168 public function test_delete_data_for_all_users_in_context() {
169 global $DB;
171 $this->resetAfterTest();
172 // Setup scenario.
173 $scenario = $this->setup_scenario();
175 // Before delete data, we have 4 contents.
176 // - 3 in a system context.
177 // - 2 in a course category context.
178 // - 5 in a course context (2 by manager and 3 by teacher).
180 // Delete data based on system context.
181 provider::delete_data_for_all_users_in_context($scenario->systemcontext);
182 $count = $DB->count_records('contentbank_content');
183 // 3 content should be deleted.
184 // 7 contents should be remain.
185 $this->assertEquals(7, $count);
187 // Delete data based on course category context.
188 provider::delete_data_for_all_users_in_context($scenario->coursecategorycontext);
189 $count = $DB->count_records('contentbank_content');
190 // 2 contents should be deleted.
191 // 5 content should be remain.
192 $this->assertEquals(5, $count);
194 // Delete data based on course context.
195 provider::delete_data_for_all_users_in_context($scenario->coursecontext);
196 $count = $DB->count_records('contentbank_content');
197 // 5 content should be deleted.
198 // 0 content should be remain.
199 $this->assertEquals(0, $count);
203 * Test for provider::test_delete_data_for_users().
205 public function test_delete_data_for_users() {
206 global $DB;
208 $this->resetAfterTest();
209 // Setup scenario.
210 $scenario = $this->setup_scenario();
212 // Before delete data, we have 4 contents.
213 // - 3 in a system context.
214 // - 2 in a course category context.
215 // - 5 in a course context (2 by manager and 3 by teacher).
217 // A list of users who has created content in Course Category Context.
218 $userlist1 = new userlist($scenario->coursecategorycontext,
219 'core_contentbank');
220 provider::get_users_in_context($userlist1);
221 $this->assertCount(1, $userlist1);
222 // Only Manager should be.
223 $this->assertEquals([$scenario->manager->id], $userlist1->get_userids());
225 // A list of users who has created content in Course Context.
226 $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
227 provider::get_users_in_context($userlist2);
228 $this->assertCount(2, $userlist2);
230 // Manager and Teacher should be.
231 $expected = [$scenario->manager->id, $scenario->teacher->id];
232 sort($expected);
233 $actual = $userlist2->get_userids();
234 sort($actual);
235 $this->assertEquals($expected, $actual);
237 // Convert $userlist1 into an approved_contextlist.
238 $approvedlist1 = new approved_userlist($scenario->coursecategorycontext, 'core_contentbank', $userlist1->get_userids());
239 // Delete data for users in course category context.
240 provider::delete_data_for_users($approvedlist1);
242 // Re-fetch users in course category context.
243 $userlist1 = new userlist($scenario->coursecategorycontext,
244 'core_contentbank');
245 provider::get_users_in_context($userlist1);
246 // The user data in course category context should be deleted.
247 $this->assertCount(0, $userlist1);
248 // Re-fetch users in course category context.
249 $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
250 provider::get_users_in_context($userlist2);
251 // The user data in course context should be still present.
252 $this->assertCount(2, $userlist2);
254 // Convert $userlist2 into an approved_contextlist.
255 $approvedlist2 = new approved_userlist($scenario->coursecontext,
256 'core_contentbank', $userlist2->get_userids());
257 // Delete data for users in course context.
258 provider::delete_data_for_users($approvedlist2);
259 $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
260 provider::get_users_in_context($userlist2);
261 // The user data in course context should be deleted.
262 $this->assertCount(0, $userlist2);
266 * Test for provider::delete_data_for_user().
268 public function test_delete_data_for_user() {
269 global $DB;
271 $this->resetAfterTest();
272 // Setup scenario.
273 $scenario = $this->setup_scenario();
275 // Before delete data, we have 4 contents.
276 // - 3 in a system context.
277 // - 2 in a course category context.
278 // - 5 in a course context (2 by manager and 3 by teacher).
280 // Get all the context for Manager.
281 $contextlist = provider::get_contexts_for_userid($scenario->manager->id);
282 $approvedcontextlist = new approved_contextlist($scenario->manager,
283 'core_contentbank', $contextlist->get_contextids());
284 // Delete all the data created by the Manager in all the contexts.
285 provider::delete_data_for_user($approvedcontextlist);
287 // After deletion, only 3 content for teacher should be present.
288 $count = $DB->count_records('contentbank_content');
289 $this->assertEquals(3, $count);
291 // Confirm that the remaining content was created by the teacher.
292 $count = $DB->count_records('contentbank_content',
293 ['usercreated' => $scenario->teacher->id]);
294 $this->assertEquals(3, $count);
296 // Get all the context for Teacher.
297 $contextlist = provider::get_contexts_for_userid($scenario->teacher->id);
298 $approvedcontextlist = new approved_contextlist($scenario->teacher,
299 'core_contentbank', $contextlist->get_contextids());
300 // Delete all the data created by the Teacher in all the contexts.
301 provider::delete_data_for_user($approvedcontextlist);
303 // After deletion, no content should be present.
304 $count = $DB->count_records('contentbank_content');
305 $this->assertEquals(0, $count);
309 * Create a complex scenario to use into the tests.
311 * @return stdClass $scenario
313 protected function setup_scenario() {
314 global $DB;
316 $systemcontext = context_system::instance();
317 $manager = $this->getDataGenerator()->create_user();
318 $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
319 $this->getDataGenerator()->role_assign($managerroleid, $manager->id);
321 $coursecategory = $this->getDataGenerator()->create_category();
322 $coursecategorycontext = context_coursecat::instance($coursecategory->id);
324 $course = $this->getDataGenerator()->create_course();
325 $coursecontext = context_course::instance($course->id);
326 $teacher = $this->getDataGenerator()->create_and_enrol($course,
327 'editingteacher');
329 // Add some content to the content bank.
330 $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
331 // Add contents by Manager in Context System.
332 $records = $generator->generate_contentbank_data('contenttype_testable',
333 1, $manager->id, $systemcontext, false, 'systemtestfile1.h5p');
334 $records = $generator->generate_contentbank_data('contenttype_testable',
335 1, $manager->id, $systemcontext, false, 'systemtestfile2.h5p');
336 $records = $generator->generate_contentbank_data('contenttype_testable',
337 1, $manager->id, $systemcontext, false, 'systemtestfile3.h5p');
338 // Add contents by Manager in Context Course Category.
339 $records = $generator->generate_contentbank_data('contenttype_testable',
340 1, $manager->id, $coursecategorycontext, false, 'coursecattestfile1.h5p');
341 $records = $generator->generate_contentbank_data('contenttype_testable',
342 1, $manager->id, $coursecategorycontext, false, 'coursecattestfile2.h5p');
343 // Add contents by Manager in Context Course.
344 $records = $generator->generate_contentbank_data('contenttype_testable',
345 1, $manager->id, $coursecontext, false, 'coursetestfile1.h5p');
346 $records = $generator->generate_contentbank_data('contenttype_testable',
347 1, $manager->id, $coursecontext, false, 'coursetestfile2.h5p');
348 // Add contents by Teacher.
349 $records = $generator->generate_contentbank_data('contenttype_testable',
350 1, $teacher->id, $coursecontext, false, 'courseteacherfile1.h5p');
351 $records = $generator->generate_contentbank_data('contenttype_testable',
352 1, $teacher->id, $coursecontext, false, 'courseteacherfile2.h5p');
353 $records = $generator->generate_contentbank_data('contenttype_testable',
354 1, $teacher->id, $coursecontext, false, 'courseteacherfile3.h5p');
356 $scenario = new stdClass();
357 $scenario->systemcontext = $systemcontext;
358 $scenario->coursecategorycontext = $coursecategorycontext;
359 $scenario->coursecontext = $coursecontext;
360 $scenario->manager = $manager;
361 $scenario->teacher = $teacher;
363 return $scenario;
367 * Ensure that export_user_preferences returns no data if the user has not visited any content bank.
369 public function test_export_user_preferences_no_pref() {
370 global $DB;
372 $this->resetAfterTest();
373 $user = $this->getDataGenerator()->create_user();
374 $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
375 $this->getDataGenerator()->role_assign($managerroleid, $user->id);
377 provider::export_user_preferences($user->id);
378 $writer = writer::with_context(context_system::instance());
379 $this->assertFalse($writer->has_any_data());
383 * Test for provider::test_export_user_preferences().
385 public function test_export_user_preferences() {
386 global $DB;
388 // Test setup.
389 $this->resetAfterTest(true);
390 $user = $this->getDataGenerator()->create_user();
391 $this->setUser($user);
393 set_user_preference('core_contentbank_view_list', 1);
394 // Test the user preferences export contains 1 user preference record for the User.
395 provider::export_user_preferences($user->id);
396 $contextuser = context_user::instance($user->id);
397 $writer = writer::with_context($contextuser);
398 $this->assertTrue($writer->has_any_data());
400 $prefs = $writer->get_user_preferences('core_contentbank');
401 $this->assertCount(1, (array) $prefs);
402 $this->assertEquals(1, $prefs->core_contentbank_view_list->value);
403 $this->assertEquals(
404 get_string('privacy:request:preference:set', 'core_contentbank', (object) [
405 'name' => 'core_contentbank_view_list',
406 'value' => $prefs->core_contentbank_view_list->value,
408 $prefs->core_contentbank_view_list->description