MDL-68483 contentbank: improve search API
[moodle.git] / contentbank / tests / contenttype_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  * Test for content bank contenttype class.
19  *
20  * @package    core_contentbank
21  * @category   test
22  * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 namespace core_contentbank;
28 defined('MOODLE_INTERNAL') || die();
30 global $CFG;
31 require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
32 require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
34 use stdClass;
35 use context_system;
36 use contenttype_testable\contenttype as contenttype;
37 /**
38  * Test for content bank contenttype class.
39  *
40  * @package    core_contentbank
41  * @category   test
42  * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
43  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44  * @coversDefaultClass \core_contentbank\contenttype
45  *
46  */
47 class core_contenttype_contenttype_testcase extends \advanced_testcase {
49     /** @var int Identifier for the manager role. */
50     protected $managerroleid;
52     /** @var stdClass Manager user. */
53     protected $manager1;
55     /** @var stdClass Manager user. */
56     protected $manager2;
58     /** @var stdClass User. */
59     protected $user;
61     /** @var array List of contents created (every user has a key with contents created by her). */
62     protected $contents = [];
64     /** @var contenttype The contenttype instance. */
65     protected $contenttype;
67     /**
68      * Tests get_contenttype_name result.
69      *
70      * @covers ::get_contenttype_name
71      */
72     public function test_get_contenttype_name() {
73         $this->resetAfterTest();
75         $systemcontext = \context_system::instance();
76         $testable = new contenttype($systemcontext);
78         $this->assertEquals('contenttype_testable', $testable->get_contenttype_name());
79     }
81     /**
82      * Tests get_plugin_name result.
83      *
84      * @covers ::get_plugin_name
85      */
86     public function test_get_plugin_name() {
87         $this->resetAfterTest();
89         $systemcontext = \context_system::instance();
90         $testable = new contenttype($systemcontext);
92         $this->assertEquals('testable', $testable->get_plugin_name());
93     }
95     /**
96      * Tests get_icon result.
97      *
98      * @covers ::get_icon
99      */
100     public function test_get_icon() {
101         $this->resetAfterTest();
103         $systemcontext = \context_system::instance();
104         $testable = new contenttype($systemcontext);
105         $icon = $testable->get_icon('new content');
106         $this->assertContains('archive', $icon);
107     }
109     /**
110      * Tests is_feature_supported behavior .
111      *
112      * @covers ::is_feature_supported
113      */
114     public function test_is_feature_supported() {
115         $this->resetAfterTest();
117         $systemcontext = \context_system::instance();
118         $testable = new contenttype($systemcontext);
120         $this->assertTrue($testable->is_feature_supported(contenttype::CAN_TEST));
121         $this->assertFalse($testable->is_feature_supported(contenttype::CAN_UPLOAD));
122     }
124     /**
125      * Tests can_upload behavior with no implemented upload feature.
126      *
127      * @covers ::can_upload
128      */
129     public function test_no_upload_feature_supported() {
130         $this->resetAfterTest();
132         $systemcontext = \context_system::instance();
133         $testable = new contenttype($systemcontext);
135         $this->setAdminUser();
136         $this->assertFalse($testable->is_feature_supported(contenttype::CAN_UPLOAD));
137         $this->assertFalse($testable->can_upload());
138     }
140     /**
141      * Test create_content() with empty data.
142      *
143      * @covers ::create_content
144      */
145     public function test_create_empty_content() {
146         $this->resetAfterTest();
148         // Create empty content.
149         $record = new stdClass();
151         $contenttype = new contenttype(context_system::instance());
152         $content = $contenttype->create_content($record);
154         $this->assertEquals('contenttype_testable', $content->get_content_type());
155         $this->assertInstanceOf('\\contenttype_testable\\content', $content);
156     }
158     /**
159      * Tests for behaviour of create_content() with data.
160      *
161      * @covers ::create_content
162      */
163     public function test_create_content() {
164         $this->resetAfterTest();
166         // Create content.
167         $record = new stdClass();
168         $record->name = 'Test content';
169         $record->configdata = '';
170         $record->contenttype = '';
172         $contenttype = new contenttype(context_system::instance());
173         $content = $contenttype->create_content($record);
175         $this->assertEquals('contenttype_testable', $content->get_content_type());
176         $this->assertInstanceOf('\\contenttype_testable\\content', $content);
177     }
179     /**
180      * Test the behaviour of can_delete().
181      */
182     public function test_can_delete() {
183         global $DB;
185         $this->resetAfterTest();
186         $this->contenttype_setup_scenario_data();
188         $managercontent = array_shift($this->contents[$this->manager1->id]);
189         $usercontent = array_shift($this->contents[$this->user->id]);
191         // Check the content has been created as expected.
192         $records = $DB->count_records('contentbank_content');
193         $this->assertEquals(4, $records);
195         // Check user can only delete records created by her.
196         $this->setUser($this->user);
197         $this->assertFalse($this->contenttype->can_delete($managercontent));
198         $this->assertTrue($this->contenttype->can_delete($usercontent));
200         // Check manager can delete records all the records created.
201         $this->setUser($this->manager1);
202         $this->assertTrue($this->contenttype->can_delete($managercontent));
203         $this->assertTrue($this->contenttype->can_delete($usercontent));
205         // Unassign capability to manager role and check not can only delete their own records.
206         unassign_capability('moodle/contentbank:deleteanycontent', $this->managerroleid);
207         $this->assertTrue($this->contenttype->can_delete($managercontent));
208         $this->assertFalse($this->contenttype->can_delete($usercontent));
209         $this->setUser($this->manager2);
210         $this->assertFalse($this->contenttype->can_delete($managercontent));
211         $this->assertFalse($this->contenttype->can_delete($usercontent));
212     }
214     /**
215      * Test the behaviour of delete_content().
216      */
217     public function test_delete_content() {
218         global $DB;
220         $this->resetAfterTest();
221         $this->contenttype_setup_scenario_data();
223         // Check the content has been created as expected.
224         $this->assertEquals(4, $DB->count_records('contentbank_content'));
226         // Check the content is deleted as expected.
227         $this->setUser($this->manager1);
228         $content = array_shift($this->contents[$this->manager1->id]);
229         $deleted = $this->contenttype->delete_content($content);
230         $this->assertTrue($deleted);
231         $this->assertEquals(3, $DB->count_records('contentbank_content'));
232     }
234     /**
235      * Helper function to setup 3 users (manager1, manager2 and user) and 4 contents (3 created by manager1 and 1 by user).
236      */
237     protected function contenttype_setup_scenario_data(): void {
238         global $DB;
239         $systemcontext = context_system::instance();
241         // Create users.
242         $this->manager1 = $this->getDataGenerator()->create_user();
243         $this->manager2 = $this->getDataGenerator()->create_user();
244         $this->managerroleid = $DB->get_field('role', 'id', array('shortname' => 'manager'));
245         $this->getDataGenerator()->role_assign($this->managerroleid, $this->manager1->id);
246         $this->getDataGenerator()->role_assign($this->managerroleid, $this->manager2->id);
247         $this->user = $this->getDataGenerator()->create_user();
249         // Add some content to the content bank.
250         $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
251         $this->contents[$this->manager1->id] = $generator->generate_contentbank_data(null, 3, $this->manager1->id);
252         $this->contents[$this->user->id] = $generator->generate_contentbank_data(null, 1, $this->user->id);
254         $this->contenttype = new \contenttype_testable\contenttype($systemcontext);
255     }
257     /**
258      * Data provider for test_rename_content.
259      *
260      * @return  array
261      */
262     public function rename_content_provider() {
263         return [
264             'Standard name' => ['New name', 'New name'],
265             'Name with digits' => ['Today is 17/04/2017', 'Today is 17/04/2017'],
266             'Name with symbols' => ['Follow us: @moodle', 'Follow us: @moodle'],
267             'Name with tags' => ['This is <b>bold</b>', 'This is bold'],
268             'Long name' => [str_repeat('a', 100), str_repeat('a', 100)],
269             'Too long name' => [str_repeat('a', 300), str_repeat('a', 255)]
270         ];
271     }
273     /**
274      * Test the behaviour of rename_content().
275      *
276      * @dataProvider    rename_content_provider
277      * @param   string  $newname    The name to set
278      * @param   string   $expected   The name result
279      *
280      * @covers ::rename_content
281      */
282     public function test_rename_content(string $newname, string $expected) {
283         global $DB;
285         $this->resetAfterTest();
287         // Create course and teacher user.
288         $course = $this->getDataGenerator()->create_course();
289         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
290         $coursecontext = \context_course::instance($course->id);
291         $contenttype = new contenttype($coursecontext);
293         // Add some content to the content bank as teacher.
294         $this->setUser($teacher);
295         $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
296         $contents = $generator->generate_contentbank_data('contenttype_testable', 1, $teacher->id);
297         $content = array_shift($contents);
299         $oldname = $content->get_name();
301         // Check the content is renamed as expected by a user with permission.
302         $renamed = $contenttype->rename_content($content, $newname);
303         $this->assertTrue($renamed);
304         $record = $DB->get_record('contentbank_content', ['id' => $content->get_id()]);
305         $this->assertNotEquals($oldname, $record->name);
306         $this->assertEquals($expected, $record->name);
307     }
309     /**
310      * Test the behaviour of can_manage().
311      *
312      * @covers ::can_manage
313      */
314     public function test_can_manage() {
315         global $DB, $USER;
317         $this->resetAfterTest();
318         $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
320         // Create course and teacher user.
321         $teacherroleid = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']);
322         $course = $this->getDataGenerator()->create_course();
323         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
324         $manager = $this->getDataGenerator()->create_and_enrol($course, 'manager');
325         $coursecontext = \context_course::instance($course->id);
327         $contenttype = new contenttype($coursecontext);
329         // Add some content to the content bank as admin.
330         $this->setAdminUser();
331         $contentsbyadmin = $generator->generate_contentbank_data('contenttype_testable', 1, $USER->id, $coursecontext);
332         $contentbyadmin = array_shift($contentsbyadmin);
334         // Add some content to the content bank as teacher.
335         $contentsbyteacher = $generator->generate_contentbank_data('contenttype_testable', 1, $teacher->id, $coursecontext);
336         $contentbyteacher = array_shift($contentsbyteacher);
338         // Check the content has been created as expected.
339         $records = $DB->count_records('contentbank_content');
340         $this->assertEquals(2, $records);
342         // Check manager can manage by default all the contents created.
343         $this->setUser($manager);
344         $this->assertTrue($contenttype->can_manage($contentbyteacher));
345         $this->assertTrue($contenttype->can_manage($contentbyadmin));
347         // Check teacher can only edit their own content.
348         $this->setUser($teacher);
349         $this->assertTrue($contenttype->can_manage($contentbyteacher));
350         $this->assertFalse($contenttype->can_manage($contentbyadmin));
352         // Unassign capability to teacher role and check they not can not edit any content.
353         unassign_capability('moodle/contentbank:manageowncontent', $teacherroleid);
354         $this->assertFalse($contenttype->can_manage($contentbyteacher));
355         $this->assertFalse($contenttype->can_manage($contentbyadmin));
356     }