Merge branch 'MDL-70125_39-3' of git://github.com/mdjnelson/moodle into MOODLE_39_STABLE
[moodle.git] / favourites / tests / repository_test.php
blobb95451a12e2c09cd76b52b77537c53b45f0241f2
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 * Testing the repository objects within core_favourites.
20 * @package core_favourites
21 * @category test
22 * @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
28 use \core_favourites\local\repository\favourite_repository;
29 use \core_favourites\local\entity\favourite;
31 /**
32 * Test class covering the favourite_repository.
34 * @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 class favourite_repository_testcase extends advanced_testcase {
39 public function setUp() {
40 $this->resetAfterTest();
43 // Basic setup stuff to be reused in most tests.
44 protected function setup_users_and_courses() {
45 $user1 = self::getDataGenerator()->create_user();
46 $user1context = \context_user::instance($user1->id);
47 $user2 = self::getDataGenerator()->create_user();
48 $user2context = \context_user::instance($user2->id);
49 $course1 = self::getDataGenerator()->create_course();
50 $course2 = self::getDataGenerator()->create_course();
51 $course1context = context_course::instance($course1->id);
52 $course2context = context_course::instance($course2->id);
53 return [$user1context, $user2context, $course1context, $course2context];
56 /**
57 * Verify the basic create operation can create records, and is validated.
59 public function test_add() {
60 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
62 // Create a favourites repository and favourite a course.
63 $favouritesrepo = new favourite_repository($user1context);
65 $favcourse = new favourite(
66 'core_course',
67 'course',
68 $course1context->instanceid,
69 $course1context->id,
70 $user1context->instanceid
72 $timenow = time(); // Reference only, to check that the created item has a time equal to or greater than this.
73 $favourite = $favouritesrepo->add($favcourse);
75 // Verify we get the record back.
76 $this->assertInstanceOf(favourite::class, $favourite);
77 $this->assertObjectHasAttribute('id', $favourite);
78 $this->assertEquals('core_course', $favourite->component);
79 $this->assertEquals('course', $favourite->itemtype);
81 // Verify the returned object has additional properties, created as part of the add.
82 $this->assertObjectHasAttribute('ordering', $favourite);
83 $this->assertObjectHasAttribute('timecreated', $favourite);
84 $this->assertGreaterThanOrEqual($timenow, $favourite->timecreated);
86 // Try to save the same record again and confirm the store throws an exception.
87 $this->expectException('dml_write_exception');
88 $favouritesrepo->add($favcourse);
91 /**
92 * Tests that malformed favourites cannot be saved.
94 public function test_add_malformed_favourite() {
95 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
97 // Create a favourites repository and favourite a course.
98 $favouritesrepo = new favourite_repository($user1context);
100 $favcourse = new favourite(
101 'core_course',
102 'course',
103 $course1context->instanceid,
104 $course1context->id,
105 $user1context->instanceid
107 $favcourse->something = 'something';
109 $this->expectException('moodle_exception');
110 $favouritesrepo->add($favcourse);
114 * Tests that incomplete favourites cannot be saved.
116 public function test_add_incomplete_favourite() {
117 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
119 // Create a favourites repository and try to favourite a course.
120 $favouritesrepo = new favourite_repository($user1context);
122 $favcourse = new favourite(
123 'core_course',
124 'course',
125 $course1context->instanceid,
126 $course1context->id,
127 $user1context->instanceid
129 unset($favcourse->userid);
131 $this->expectException('moodle_exception');
132 $favouritesrepo->add($favcourse);
135 public function test_add_all_basic() {
136 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
138 // Create a favourites repository and favourite several courses.
139 $favouritesrepo = new favourite_repository($user1context);
140 $favcourses = [];
142 $favcourses[] = new favourite(
143 'core_course',
144 'course',
145 $course1context->instanceid,
146 $course1context->id,
147 $user1context->instanceid
149 $favcourses[] = new favourite(
150 'core_course',
151 'course',
152 $course2context->instanceid,
153 $course2context->id,
154 $user1context->instanceid
157 $timenow = time(); // Reference only, to check that the created item has a time equal to or greater than this.
158 $favourites = $favouritesrepo->add_all($favcourses);
160 $this->assertIsArray($favourites);
161 $this->assertCount(2, $favourites);
162 foreach ($favourites as $favourite) {
163 // Verify we get the favourite back.
164 $this->assertInstanceOf(favourite::class, $favourite);
165 $this->assertEquals('core_course', $favourite->component);
166 $this->assertEquals('course', $favourite->itemtype);
168 // Verify the returned object has additional properties, created as part of the add.
169 $this->assertObjectHasAttribute('ordering', $favourite);
170 $this->assertObjectHasAttribute('timecreated', $favourite);
171 $this->assertGreaterThanOrEqual($timenow, $favourite->timecreated);
174 // Try to save the same record again and confirm the store throws an exception.
175 $this->expectException('dml_write_exception');
176 $favouritesrepo->add_all($favcourses);
180 * Tests reading from the repository by instance id.
182 public function test_find() {
183 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
185 // Create a favourites repository and favourite a course.
186 $favouritesrepo = new favourite_repository($user1context);
187 $favourite = new favourite(
188 'core_course',
189 'course',
190 $course1context->instanceid,
191 $course1context->id,
192 $user1context->instanceid
194 $favourite = $favouritesrepo->add($favourite);
196 // Now, from the repo, get the single favourite we just created, by id.
197 $userfavourite = $favouritesrepo->find($favourite->id);
198 $this->assertInstanceOf(favourite::class, $userfavourite);
199 $this->assertObjectHasAttribute('timecreated', $userfavourite);
201 // Try to get a favourite we know doesn't exist.
202 // We expect an exception in this case.
203 $this->expectException(dml_exception::class);
204 $favouritesrepo->find(0);
208 * Test verifying that find_all() returns all favourites, or an empty array.
210 public function test_find_all() {
211 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
213 $favouritesrepo = new favourite_repository($user1context);
215 // Verify that only two self-conversations are found.
216 $this->assertCount(2, $favouritesrepo->find_all());
218 // Save a favourite for 2 courses, in different areas.
219 $favourite = new favourite(
220 'core_course',
221 'course',
222 $course1context->instanceid,
223 $course1context->id,
224 $user1context->instanceid
226 $favourite2 = new favourite(
227 'core_course',
228 'course',
229 $course2context->instanceid,
230 $course2context->id,
231 $user1context->instanceid
233 $favouritesrepo->add($favourite);
234 $favouritesrepo->add($favourite2);
236 // Verify that find_all returns both of our favourites + two self-conversations.
237 $favourites = $favouritesrepo->find_all();
238 $this->assertCount(4, $favourites);
239 foreach ($favourites as $fav) {
240 $this->assertInstanceOf(favourite::class, $fav);
241 $this->assertObjectHasAttribute('id', $fav);
242 $this->assertObjectHasAttribute('timecreated', $fav);
247 * Testing the pagination of the find_all method.
249 public function test_find_all_pagination() {
250 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
252 $favouritesrepo = new favourite_repository($user1context);
254 // Verify that for an empty repository, find_all with any combination of page options returns only self-conversations.
255 $this->assertCount(2, $favouritesrepo->find_all(0, 0));
256 $this->assertCount(2, $favouritesrepo->find_all(0, 10));
257 $this->assertCount(1, $favouritesrepo->find_all(1, 0));
258 $this->assertCount(1, $favouritesrepo->find_all(1, 10));
260 // Save 10 arbitrary favourites to the repo.
261 foreach (range(1, 10) as $i) {
262 $favourite = new favourite(
263 'core_course',
264 'course',
266 $course1context->id,
267 $user1context->instanceid
269 $favouritesrepo->add($favourite);
272 // Verify we have 10 favourites + 2 self-conversations.
273 $this->assertEquals(12, $favouritesrepo->count());
275 // Verify we can fetch the first page of 5 records+ 2 self-conversations.
276 $favourites = $favouritesrepo->find_all(0, 6);
277 $this->assertCount(6, $favourites);
279 // Verify we can fetch the second page.
280 $favourites = $favouritesrepo->find_all(6, 6);
281 $this->assertCount(6, $favourites);
283 // Verify the third page request ends with an empty array.
284 $favourites = $favouritesrepo->find_all(12, 6);
285 $this->assertCount(0, $favourites);
289 * Test retrieval of a user's favourites for a given criteria, in this case, area.
291 public function test_find_by() {
292 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
294 // Create a favourites repository and favourite a course.
295 $favouritesrepo = new favourite_repository($user1context);
296 $favourite = new favourite(
297 'core_course',
298 'course',
299 $course1context->instanceid,
300 $course1context->id,
301 $user1context->instanceid
303 $favouritesrepo->add($favourite);
305 // Add another favourite.
306 $favourite = new favourite(
307 'core_course',
308 'course_item',
309 $course1context->instanceid,
310 $course1context->id,
311 $user1context->instanceid
313 $favouritesrepo->add($favourite);
315 // From the repo, get the list of favourites for the 'core_course/course' area.
316 $userfavourites = $favouritesrepo->find_by(['component' => 'core_course', 'itemtype' => 'course']);
317 $this->assertIsArray($userfavourites);
318 $this->assertCount(1, $userfavourites);
320 // Try to get a list of favourites for a non-existent area.
321 $userfavourites = $favouritesrepo->find_by(['component' => 'core_cannibalism', 'itemtype' => 'course']);
322 $this->assertIsArray($userfavourites);
323 $this->assertCount(0, $userfavourites);
325 // From the repo, get the list of favourites for the 'core_course/course' area when passed as an array.
326 $userfavourites = $favouritesrepo->find_by(['component' => 'core_course', 'itemtype' => ['course']]);
327 $this->assertIsArray($userfavourites);
328 $this->assertCount(1, $userfavourites);
330 // From the repo, get the list of favourites for the 'core_course' area given multiple item_types.
331 $userfavourites = $favouritesrepo->find_by(['component' => 'core_course', 'itemtype' => ['course', 'course_item']]);
332 $this->assertIsArray($userfavourites);
333 $this->assertCount(2, $userfavourites);
337 * Testing the pagination of the find_by method.
339 public function test_find_by_pagination() {
340 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
342 $favouritesrepo = new favourite_repository($user1context);
344 // Verify that by default, find_all with any combination of page options returns only self-conversations.
345 $this->assertCount(2, $favouritesrepo->find_by([], 0, 0));
346 $this->assertCount(2, $favouritesrepo->find_by([], 0, 10));
347 $this->assertCount(1, $favouritesrepo->find_by([], 1, 0));
348 $this->assertCount(1, $favouritesrepo->find_by([], 1, 10));
350 // Save 10 arbitrary favourites to the repo.
351 foreach (range(1, 10) as $i) {
352 $favourite = new favourite(
353 'core_course',
354 'course',
356 $course1context->id,
357 $user1context->instanceid
359 $favouritesrepo->add($favourite);
362 // Verify we have 10 favourites + 2 self-conversations.
363 $this->assertEquals(12, $favouritesrepo->count());
365 // Verify a request for a page, when no criteria match, results in 2 self-conversations array.
366 $favourites = $favouritesrepo->find_by(['component' => 'core_message'], 0, 5);
367 $this->assertCount(2, $favourites);
369 // Verify we can fetch a the first page of 5 records.
370 $favourites = $favouritesrepo->find_by(['component' => 'core_course'], 0, 5);
371 $this->assertCount(5, $favourites);
373 // Verify we can fetch the second page.
374 $favourites = $favouritesrepo->find_by(['component' => 'core_course'], 5, 5);
375 $this->assertCount(5, $favourites);
377 // Verify the third page request ends with an empty array.
378 $favourites = $favouritesrepo->find_by(['component' => 'core_course'], 10, 5);
379 $this->assertCount(0, $favourites);
383 * Test the count_by() method.
385 public function test_count_by() {
386 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
388 // Create a favourites repository and add 2 favourites in different areas.
389 $favouritesrepo = new favourite_repository($user1context);
390 $favourite = new favourite(
391 'core_course',
392 'course',
393 $course1context->instanceid,
394 $course1context->id,
395 $user1context->instanceid
397 $favourite2 = new favourite(
398 'core_course',
399 'anothertype',
400 $course2context->instanceid,
401 $course2context->id,
402 $user1context->instanceid
404 $favouritesrepo->add($favourite);
405 $favouritesrepo->add($favourite2);
407 // Verify counts can be restricted by criteria.
408 $this->assertEquals(1, $favouritesrepo->count_by(['userid' => $user1context->instanceid, 'component' => 'core_course',
409 'itemtype' => 'course']));
410 $this->assertEquals(1, $favouritesrepo->count_by(['userid' => $user1context->instanceid, 'component' => 'core_course',
411 'itemtype' => 'anothertype']));
412 $this->assertEquals(0, $favouritesrepo->count_by(['userid' => $user1context->instanceid, 'component' => 'core_course',
413 'itemtype' => 'nonexistenttype']));
417 * Test the exists() function.
419 public function test_exists() {
420 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
422 // Create a favourites repository and favourite a course.
423 $favouritesrepo = new favourite_repository($user1context);
424 $favourite = new favourite(
425 'core_course',
426 'course',
427 $course1context->instanceid,
428 $course1context->id,
429 $user1context->instanceid
431 $createdfavourite = $favouritesrepo->add($favourite);
433 // Verify the existence of the favourite in the repo.
434 $this->assertTrue($favouritesrepo->exists($createdfavourite->id));
436 // Verify exists returns false for non-existent favourite.
437 $this->assertFalse($favouritesrepo->exists(0));
441 * Test the exists_by() method.
443 public function test_exists_by() {
444 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
446 // Create a favourites repository and favourite two courses, in different areas.
447 $favouritesrepo = new favourite_repository($user1context);
448 $favourite = new favourite(
449 'core_course',
450 'course',
451 $course1context->instanceid,
452 $course1context->id,
453 $user1context->instanceid
455 $favourite2 = new favourite(
456 'core_course',
457 'anothertype',
458 $course2context->instanceid,
459 $course2context->id,
460 $user1context->instanceid
462 $favourite1 = $favouritesrepo->add($favourite);
463 $favourite2 = $favouritesrepo->add($favourite2);
465 // Verify the existence of the favourites.
466 $this->assertTrue($favouritesrepo->exists_by(
468 'userid' => $user1context->instanceid,
469 'component' => 'core_course',
470 'itemtype' => 'course',
471 'itemid' => $favourite1->itemid,
472 'contextid' => $favourite1->contextid
475 $this->assertTrue($favouritesrepo->exists_by(
477 'userid' => $user1context->instanceid,
478 'component' => 'core_course',
479 'itemtype' => 'anothertype',
480 'itemid' => $favourite2->itemid,
481 'contextid' => $favourite2->contextid
485 // Verify that we can't find a favourite from one area, in another.
486 $this->assertFalse($favouritesrepo->exists_by(
488 'userid' => $user1context->instanceid,
489 'component' => 'core_course',
490 'itemtype' => 'anothertype',
491 'itemid' => $favourite1->itemid,
492 'contextid' => $favourite1->contextid
498 * Test the update() method, by simulating a user changing the ordering of a favourite.
500 public function test_update() {
501 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
503 // Create a favourites repository and favourite a course.
504 $favouritesrepo = new favourite_repository($user1context);
505 $favourite = new favourite(
506 'core_course',
507 'course',
508 $course1context->instanceid,
509 $course1context->id,
510 $user1context->instanceid
512 $favourite1 = $favouritesrepo->add($favourite);
513 $this->assertNull($favourite1->ordering);
515 // Verify we can update the ordering for 2 favourites.
516 $favourite1->ordering = 1;
517 $favourite1 = $favouritesrepo->update($favourite1);
518 $this->assertInstanceOf(favourite::class, $favourite1);
519 $this->assertEquals('1', $favourite1->ordering);
522 public function test_delete() {
523 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
525 // Create a favourites repository and favourite a course.
526 $favouritesrepo = new favourite_repository($user1context);
527 $favourite = new favourite(
528 'core_course',
529 'course',
530 $course1context->instanceid,
531 $course1context->id,
532 $user1context->instanceid
534 $favourite = $favouritesrepo->add($favourite);
536 // Verify the existence of the favourite in the repo.
537 $this->assertTrue($favouritesrepo->exists($favourite->id));
539 // Now, delete the favourite and confirm it's not retrievable.
540 $favouritesrepo->delete($favourite->id);
541 $this->assertFalse($favouritesrepo->exists($favourite->id));
545 * Test the delete_by() method.
547 public function test_delete_by() {
548 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
550 // Create a favourites repository and favourite two courses, in different areas.
551 $favouritesrepo = new favourite_repository($user1context);
552 $favourite = new favourite(
553 'core_course',
554 'course',
555 $course1context->instanceid,
556 $course1context->id,
557 $user1context->instanceid
559 $favourite2 = new favourite(
560 'core_course',
561 'anothertype',
562 $course1context->instanceid,
563 $course1context->id,
564 $user1context->instanceid
566 $favourite1 = $favouritesrepo->add($favourite);
567 $favourite2 = $favouritesrepo->add($favourite2);
569 // Verify we have 2 items in the repo + 2 self-conversations.
570 $this->assertEquals(4, $favouritesrepo->count());
572 // Try to delete by a non-existent area, and confirm it doesn't remove anything.
573 $favouritesrepo->delete_by(
575 'userid' => $user1context->instanceid,
576 'component' => 'core_course',
577 'itemtype' => 'donaldduck'
580 $this->assertEquals(4, $favouritesrepo->count());
582 // Try to delete by a non-existent area, and confirm it doesn't remove anything.
583 $favouritesrepo->delete_by(
585 'userid' => $user1context->instanceid,
586 'component' => 'core_course',
587 'itemtype' => 'cat'
590 $this->assertEquals(4, $favouritesrepo->count());
592 // Delete by area, and confirm we have one record left, from the 'core_course/anothertype' area.
593 $favouritesrepo->delete_by(
595 'userid' => $user1context->instanceid,
596 'component' => 'core_course',
597 'itemtype' => 'course'
600 $this->assertEquals(3, $favouritesrepo->count());
601 $this->assertFalse($favouritesrepo->exists($favourite1->id));
602 $this->assertTrue($favouritesrepo->exists($favourite2->id));
606 * Test the find_favourite() method for an existing favourite.
608 public function test_find_favourite_basic() {
609 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
611 // Create a favourites repository and favourite two courses, in different areas.
612 $favouritesrepo = new favourite_repository($user1context);
613 $favourite = new favourite(
614 'core_course',
615 'course',
616 $course1context->instanceid,
617 $course1context->id,
618 $user1context->instanceid
620 $favourite2 = new favourite(
621 'core_course',
622 'anothertype',
623 $course1context->instanceid,
624 $course1context->id,
625 $user1context->instanceid
627 $favourite1 = $favouritesrepo->add($favourite);
628 $favourite2 = $favouritesrepo->add($favourite2);
630 $fav = $favouritesrepo->find_favourite($user1context->instanceid, 'core_course', 'course', $course1context->instanceid,
631 $course1context->id);
632 $this->assertInstanceOf(\core_favourites\local\entity\favourite::class, $fav);
636 * Test confirming the repository throws an exception in find_favourite if the favourite can't be found.
638 public function test_find_favourite_nonexistent_favourite() {
639 list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
641 // Confirm we get an exception.
642 $favouritesrepo = new favourite_repository($user1context);
643 $this->expectException(\dml_exception::class);
644 $favouritesrepo->find_favourite($user1context->instanceid, 'core_course', 'course', 0, $course1context->id);