MDL-70102 PHPunit: Core test fails with weird added modules
[moodle.git] / course / tests / services_content_item_service_test.php
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/>.
17 /**
18  * Contains the tests for the content_item_service class.
19  *
20  * @package    core
21  * @subpackage course
22  * @copyright  2020 Jake Dallimore <jrhdallimore@gmail.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
25 namespace tests\course;
27 defined('MOODLE_INTERNAL') || die();
29 use \core_course\local\service\content_item_service;
30 use \core_course\local\repository\content_item_readonly_repository;
32 /**
33  * The tests for the content_item_service class.
34  *
35  * @copyright  2020 Jake Dallimore <jrhdallimore@gmail.com>
36  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class services_content_item_service_testcase extends \advanced_testcase {
40     /**
41      * Test confirming that content items are returned by the service.
42      */
43     public function test_get_content_items_for_user_in_course_basic() {
44         $this->resetAfterTest();
46         // Create a user in a course.
47         $course = $this->getDataGenerator()->create_course();
48         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
50         $cis = new content_item_service(new content_item_readonly_repository());
51         $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
53         foreach ($contentitems as $key => $contentitem) {
54             $this->assertObjectHasAttribute('id', $contentitem);
55             $this->assertObjectHasAttribute('name', $contentitem);
56             $this->assertObjectHasAttribute('title', $contentitem);
57             $this->assertObjectHasAttribute('link', $contentitem);
58             $this->assertObjectHasAttribute('icon', $contentitem);
59             $this->assertObjectHasAttribute('help', $contentitem);
60             $this->assertObjectHasAttribute('archetype', $contentitem);
61             $this->assertObjectHasAttribute('componentname', $contentitem);
62         }
63     }
65     /**
66      * Test confirming that access control is performed when asking the service to return content items for a user in a course.
67      */
68     public function test_get_content_items_for_user_in_course_permissions() {
69         $this->resetAfterTest();
70         global $DB;
72         // Create a user in a course.
73         $course = $this->getDataGenerator()->create_course();
74         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
76         // No cap override, so assign should be returned.
77         $cis = new content_item_service(new content_item_readonly_repository());
78         $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
79         $this->assertContains('assign', array_column($contentitems, 'name'));
81         // Override the capability 'mod/assign:addinstance' for the 'editing teacher' role.
82         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
83         assign_capability('mod/assign:addinstance', CAP_PROHIBIT, $teacherrole->id, \context_course::instance($course->id));
85         $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
86         $this->assertArrayNotHasKey('assign', $contentitems);
87     }
89     /**
90      * Test confirming that params can be added to the content item's link.
91      */
92     public function test_get_content_item_for_user_in_course_link_params() {
93         $this->resetAfterTest();
95         // Create a user in a course.
96         $course = $this->getDataGenerator()->create_course();
97         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
99         $cis = new content_item_service(new content_item_readonly_repository());
100         $contentitems = $cis->get_content_items_for_user_in_course($user, $course, ['sr' => 7]);
102         foreach ($contentitems as $item) {
103             $this->assertStringContainsString('sr=7', $item->link);
104         }
105     }
107     /**
108      * Test confirming that all content items can be fetched irrespective of permissions.
109      */
110     public function test_get_all_content_items() {
111         $this->resetAfterTest();
112         global $DB;
114         // Create a user in a course.
115         $course = $this->getDataGenerator()->create_course();
116         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
118         $cis = new content_item_service(new content_item_readonly_repository());
119         $allcontentitems = $cis->get_all_content_items($user);
120         $coursecontentitems = $cis->get_content_items_for_user_in_course($user, $course);
122         // The call to get_all_content_items() should return the same items as for the course,
123         // given the user in an editing teacher and can add manual lti instances.
124         $this->assertContains('lti', array_column($coursecontentitems, 'name'));
125         $this->assertContains('lti', array_column($allcontentitems, 'name'));
127         // Now removing the cap 'mod/lti:addinstance'. This will restrict those items returned by the course-specific method.
128         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
129         assign_capability('mod/lti:addinstance', CAP_PROHIBIT, $teacherrole->id, \context_course::instance($course->id));
131         // Verify that all items, including lti, are still returned by the get_all_content_items() call.
132         $allcontentitems = $cis->get_all_content_items($user);
133         $coursecontentitems = $cis->get_content_items_for_user_in_course($user, $course);
134         $this->assertNotContains('lti', array_column($coursecontentitems, 'name'));
135         $this->assertContains('lti', array_column($allcontentitems, 'name'));
136     }
138     /**
139      * Test confirming that content items which title match a certain pattern can be fetched irrespective of permissions.
140      */
141     public function test_get_content_items_by_name_pattern() {
142         $this->resetAfterTest();
144         // Create a user in a course.
145         $course = $this->getDataGenerator()->create_course();
146         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
148         // Pattern that does exist.
149         $pattern1 = "assign";
150         // Pattern that does not exist.
151         $pattern2 = "random string";
153         $cis = new content_item_service(new content_item_readonly_repository());
154         $matchingcontentitems1 = $cis->get_content_items_by_name_pattern($user, $pattern1);
155         $matchingcontentitems2 = $cis->get_content_items_by_name_pattern($user, $pattern2);
157         // The pattern "assign" should return at least 1 content item (ex. "Assignment").
158         $this->assertGreaterThanOrEqual(1, count($matchingcontentitems1));
159         // Verify the pattern "assign" can be found in the title of each returned content item.
160         foreach ($matchingcontentitems1 as $contentitem) {
161             $this->assertEquals(1, preg_match("/$pattern1/i", $contentitem->title));
162         }
163         // The pattern "random string" should not return any content items.
164         $this->assertEmpty($matchingcontentitems2);
165     }
167     /**
168      * Test confirming that a content item can be added to a user's favourites.
169      */
170     public function test_add_to_user_favourites() {
171         $this->resetAfterTest();
173         // Create a user in a course.
174         $course = $this->getDataGenerator()->create_course();
175         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
176         $cis = new content_item_service(new content_item_readonly_repository());
178         // Grab a the assign content item, which we'll favourite for the user.
179         $items = $cis->get_all_content_items($user);
180         $assign = $items[array_search('assign', array_column($items, 'name'))];
181         $contentitem = $cis->add_to_user_favourites($user, 'mod_assign', $assign->id);
183         // Verify the exported result is marked as a favourite.
184         $this->assertEquals('assign', $contentitem->name);
185         $this->assertTrue($contentitem->favourite);
187         // Verify the item is marked as a favourite when returned from the other service methods.
188         $allitems = $cis->get_all_content_items($user);
189         $allitemsassign = $allitems[array_search('assign', array_column($allitems, 'name'))];
191         $courseitems = $cis->get_content_items_for_user_in_course($user, $course);
192         $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
193         $this->assertTrue($allitemsassign->favourite);
194         $this->assertTrue($courseitemsassign->favourite);
195     }
197     /**
198      * Test verifying that content items can be removed from a user's favourites.
199      */
200     public function test_remove_from_user_favourites() {
201         $this->resetAfterTest();
203         // Create a user in a course.
204         $course = $this->getDataGenerator()->create_course();
205         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
206         $cis = new content_item_service(new content_item_readonly_repository());
208         // Grab a the assign content item, which we'll favourite for the user.
209         $items = $cis->get_all_content_items($user);
210         $assign = $items[array_search('assign', array_column($items, 'name'))];
211         $cis->add_to_user_favourites($user, 'mod_assign', $assign->id);
213         // Now, remove the favourite, and verify it.
214         $contentitem = $cis->remove_from_user_favourites($user, 'mod_assign', $assign->id);
216         // Verify the exported result is not marked as a favourite.
217         $this->assertEquals('assign', $contentitem->name);
218         $this->assertFalse($contentitem->favourite);
220         // Verify the item is not marked as a favourite when returned from the other service methods.
221         $allitems = $cis->get_all_content_items($user);
222         $allitemsassign = $allitems[array_search('assign', array_column($allitems, 'name'))];
223         $courseitems = $cis->get_content_items_for_user_in_course($user, $course);
224         $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
225         $this->assertFalse($allitemsassign->favourite);
226         $this->assertFalse($courseitemsassign->favourite);
227     }
229     /**
230      * Test that toggling a recommendation works as anticipated.
231      */
232     public function test_toggle_recommendation() {
233         $this->resetAfterTest();
235         // Create a user in a course.
236         $course = $this->getDataGenerator()->create_course();
237         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
238         $cis = new content_item_service(new content_item_readonly_repository());
240         // Grab a the assign content item, which we'll recommend for the user.
241         $items = $cis->get_all_content_items($user);
242         $assign = $items[array_search('assign', array_column($items, 'name'))];
243         $result = $cis->toggle_recommendation($assign->componentname, $assign->id);
244         $this->assertTrue($result);
246         $courseitems = $cis->get_all_content_items($user);
247         $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
248         $this->assertTrue($courseitemsassign->recommended);
250         // Let's toggle the recommendation off.
251         $result = $cis->toggle_recommendation($assign->componentname, $assign->id);
252         $this->assertFalse($result);
254         $courseitems = $cis->get_all_content_items($user);
255         $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
256         $this->assertFalse($courseitemsassign->recommended);
257     }