See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
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/>. 16 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 */ 25 26 namespace core_contentbank; 27 28 use stdClass; 29 use context_system; 30 use context_user; 31 use Exception; 32 use contenttype_testable\contenttype as contenttype; 33 /** 34 * Test for content bank contenttype class. 35 * 36 * @package core_contentbank 37 * @category test 38 * @copyright 2020 Amaia Anabitarte <amaia@moodle.com> 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 * @coversDefaultClass \core_contentbank\contenttype 41 * 42 */ 43 class core_contenttype_contenttype_testcase extends \advanced_testcase { 44 45 /** @var int Identifier for the manager role. */ 46 protected $managerroleid; 47 48 /** @var stdClass Manager user. */ 49 protected $manager1; 50 51 /** @var stdClass Manager user. */ 52 protected $manager2; 53 54 /** @var stdClass User. */ 55 protected $user; 56 57 /** @var array List of contents created (every user has a key with contents created by her). */ 58 protected $contents = []; 59 60 /** @var contenttype The contenttype instance. */ 61 protected $contenttype; 62 63 /** 64 * Setup to ensure that fixtures are loaded. 65 */ 66 public static function setupBeforeClass(): void { 67 global $CFG; 68 69 require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php'); 70 require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php'); 71 } 72 73 /** 74 * Tests get_contenttype_name result. 75 * 76 * @covers ::get_contenttype_name 77 */ 78 public function test_get_contenttype_name() { 79 $this->resetAfterTest(); 80 81 $systemcontext = \context_system::instance(); 82 $testable = new contenttype($systemcontext); 83 84 $this->assertEquals('contenttype_testable', $testable->get_contenttype_name()); 85 } 86 87 /** 88 * Tests get_plugin_name result. 89 * 90 * @covers ::get_plugin_name 91 */ 92 public function test_get_plugin_name() { 93 $this->resetAfterTest(); 94 95 $systemcontext = \context_system::instance(); 96 $testable = new contenttype($systemcontext); 97 98 $this->assertEquals('testable', $testable->get_plugin_name()); 99 } 100 101 /** 102 * Tests get_icon result. 103 * 104 * @covers ::get_icon 105 */ 106 public function test_get_icon() { 107 $this->resetAfterTest(); 108 109 $systemcontext = \context_system::instance(); 110 $testable = new contenttype($systemcontext); 111 $record = new stdClass(); 112 $record->name = 'New content'; 113 $content = $testable->create_content($record); 114 $icon = $testable->get_icon($content); 115 $this->assertContains('archive', $icon); 116 } 117 118 /** 119 * Tests is_feature_supported behavior . 120 * 121 * @covers ::is_feature_supported 122 */ 123 public function test_is_feature_supported() { 124 $this->resetAfterTest(); 125 126 $systemcontext = \context_system::instance(); 127 $testable = new contenttype($systemcontext); 128 129 $this->assertTrue($testable->is_feature_supported(contenttype::CAN_TEST)); 130 $this->assertFalse($testable->is_feature_supported(contenttype::CAN_UPLOAD)); 131 } 132 133 /** 134 * Tests can_upload behavior with no implemented upload feature. 135 * 136 * @covers ::can_upload 137 */ 138 public function test_no_upload_feature_supported() { 139 $this->resetAfterTest(); 140 141 $systemcontext = \context_system::instance(); 142 $testable = new contenttype($systemcontext); 143 144 $this->setAdminUser(); 145 $this->assertFalse($testable->is_feature_supported(contenttype::CAN_UPLOAD)); 146 $this->assertFalse($testable->can_upload()); 147 } 148 149 /** 150 * Test create_content() with empty data. 151 * 152 * @covers ::create_content 153 */ 154 public function test_create_empty_content() { 155 $this->resetAfterTest(); 156 157 // Create empty content. 158 $record = new stdClass(); 159 160 $contenttype = new contenttype(context_system::instance()); 161 $content = $contenttype->create_content($record); 162 163 $this->assertEquals('contenttype_testable', $content->get_content_type()); 164 $this->assertInstanceOf('\\contenttype_testable\\content', $content); 165 } 166 167 /** 168 * Tests for behaviour of create_content() with data. 169 * 170 * @covers ::create_content 171 */ 172 public function test_create_content() { 173 $this->resetAfterTest(); 174 175 // Create content. 176 $record = new stdClass(); 177 $record->name = 'Test content'; 178 $record->configdata = ''; 179 $record->contenttype = ''; 180 181 $contenttype = new contenttype(context_system::instance()); 182 $content = $contenttype->create_content($record); 183 184 $this->assertEquals('contenttype_testable', $content->get_content_type()); 185 $this->assertInstanceOf('\\contenttype_testable\\content', $content); 186 } 187 188 /** 189 * Tests for behaviour of upload_content() with a file and a record. 190 * 191 * @dataProvider upload_content_provider 192 * @param bool $userecord if a predefined record has to be used. 193 * 194 * @covers ::upload_content 195 */ 196 public function test_upload_content(bool $userecord): void { 197 global $USER; 198 199 $this->resetAfterTest(); 200 $this->setAdminUser(); 201 202 $dummy = [ 203 'contextid' => context_user::instance($USER->id)->id, 204 'component' => 'user', 205 'filearea' => 'draft', 206 'itemid' => 1, 207 'filepath' => '/', 208 'filename' => 'file.h5p', 209 'userid' => $USER->id, 210 ]; 211 $fs = get_file_storage(); 212 $dummyfile = $fs->create_file_from_string($dummy, 'Dummy content'); 213 214 // Create content. 215 if ($userecord) { 216 $record = new stdClass(); 217 $record->name = 'Test content'; 218 $record->configdata = ''; 219 $record->contenttype = ''; 220 $checkname = $record->name; 221 } else { 222 $record = null; 223 $checkname = $dummyfile->get_filename(); 224 } 225 226 $contenttype = new contenttype(context_system::instance()); 227 $content = $contenttype->upload_content($dummyfile, $record); 228 229 $this->assertEquals('contenttype_testable', $content->get_content_type()); 230 $this->assertEquals($checkname, $content->get_name()); 231 $this->assertInstanceOf('\\contenttype_testable\\content', $content); 232 233 $file = $content->get_file(); 234 $this->assertEquals($dummyfile->get_filename(), $file->get_filename()); 235 $this->assertEquals($dummyfile->get_userid(), $file->get_userid()); 236 $this->assertEquals($dummyfile->get_mimetype(), $file->get_mimetype()); 237 $this->assertEquals($dummyfile->get_contenthash(), $file->get_contenthash()); 238 $this->assertEquals('contentbank', $file->get_component()); 239 $this->assertEquals('public', $file->get_filearea()); 240 $this->assertEquals('/', $file->get_filepath()); 241 } 242 243 /** 244 * Data provider for test_rename_content. 245 * 246 * @return array 247 */ 248 public function upload_content_provider() { 249 return [ 250 'With record' => [true], 251 'Without record' => [false], 252 ]; 253 } 254 255 /** 256 * Tests for behaviour of upload_content() with a file wrong file. 257 * 258 * @covers ::upload_content 259 */ 260 public function test_upload_content_exception(): void { 261 global $USER, $DB; 262 263 $this->resetAfterTest(); 264 $this->setAdminUser(); 265 266 // The testing contenttype thows exception if filename is "error.*". 267 $dummy = [ 268 'contextid' => context_user::instance($USER->id)->id, 269 'component' => 'user', 270 'filearea' => 'draft', 271 'itemid' => 1, 272 'filepath' => '/', 273 'filename' => 'error.txt', 274 'userid' => $USER->id, 275 ]; 276 $fs = get_file_storage(); 277 $dummyfile = $fs->create_file_from_string($dummy, 'Dummy content'); 278 279 $contenttype = new contenttype(context_system::instance()); 280 $cbcontents = $DB->count_records('contentbank_content'); 281 282 // We need to capture the exception to check no content is created. 283 try { 284 $content = $contenttype->upload_content($dummyfile); 285 $this->assertTrue(false); 286 } catch (Exception $e) { 287 $this->assertTrue(true); 288 } 289 $this->assertEquals($cbcontents, $DB->count_records('contentbank_content')); 290 $this->assertEquals(1, $DB->count_records('files', ['contenthash' => $dummyfile->get_contenthash()])); 291 } 292 293 /** 294 * Test the behaviour of can_delete(). 295 */ 296 public function test_can_delete() { 297 global $DB; 298 299 $this->resetAfterTest(); 300 $this->contenttype_setup_scenario_data(); 301 302 $managercontent = array_shift($this->contents[$this->manager1->id]); 303 $usercontent = array_shift($this->contents[$this->user->id]); 304 305 // Check the content has been created as expected. 306 $records = $DB->count_records('contentbank_content'); 307 $this->assertEquals(4, $records); 308 309 // Check user can only delete records created by her. 310 $this->setUser($this->user); 311 $this->assertFalse($this->contenttype->can_delete($managercontent)); 312 $this->assertTrue($this->contenttype->can_delete($usercontent)); 313 314 // Check manager can delete records all the records created. 315 $this->setUser($this->manager1); 316 $this->assertTrue($this->contenttype->can_delete($managercontent)); 317 $this->assertTrue($this->contenttype->can_delete($usercontent)); 318 319 // Unassign capability to manager role and check not can only delete their own records. 320 unassign_capability('moodle/contentbank:deleteanycontent', $this->managerroleid); 321 $this->assertTrue($this->contenttype->can_delete($managercontent)); 322 $this->assertFalse($this->contenttype->can_delete($usercontent)); 323 $this->setUser($this->manager2); 324 $this->assertFalse($this->contenttype->can_delete($managercontent)); 325 $this->assertFalse($this->contenttype->can_delete($usercontent)); 326 } 327 328 /** 329 * Test the behaviour of delete_content(). 330 */ 331 public function test_delete_content() { 332 global $DB; 333 334 $this->resetAfterTest(); 335 $this->contenttype_setup_scenario_data(); 336 337 // Check the content has been created as expected. 338 $this->assertEquals(4, $DB->count_records('contentbank_content')); 339 340 // Check the content is deleted as expected. 341 $this->setUser($this->manager1); 342 $content = array_shift($this->contents[$this->manager1->id]); 343 $deleted = $this->contenttype->delete_content($content); 344 $this->assertTrue($deleted); 345 $this->assertEquals(3, $DB->count_records('contentbank_content')); 346 } 347 348 /** 349 * Helper function to setup 3 users (manager1, manager2 and user) and 4 contents (3 created by manager1 and 1 by user). 350 */ 351 protected function contenttype_setup_scenario_data(): void { 352 global $DB; 353 $systemcontext = context_system::instance(); 354 355 // Create users. 356 $this->manager1 = $this->getDataGenerator()->create_user(); 357 $this->manager2 = $this->getDataGenerator()->create_user(); 358 $this->managerroleid = $DB->get_field('role', 'id', array('shortname' => 'manager')); 359 $this->getDataGenerator()->role_assign($this->managerroleid, $this->manager1->id); 360 $this->getDataGenerator()->role_assign($this->managerroleid, $this->manager2->id); 361 $this->user = $this->getDataGenerator()->create_user(); 362 363 // Add some content to the content bank. 364 $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); 365 $this->contents[$this->manager1->id] = $generator->generate_contentbank_data(null, 3, $this->manager1->id); 366 $this->contents[$this->user->id] = $generator->generate_contentbank_data(null, 1, $this->user->id); 367 368 $this->contenttype = new \contenttype_testable\contenttype($systemcontext); 369 } 370 371 /** 372 * Data provider for test_rename_content. 373 * 374 * @return array 375 */ 376 public function rename_content_provider() { 377 return [ 378 'Standard name' => ['New name', 'New name', true], 379 'Name with digits' => ['Today is 17/04/2017', 'Today is 17/04/2017', true], 380 'Name with symbols' => ['Follow us: @moodle', 'Follow us: @moodle', true], 381 'Name with tags' => ['This is <b>bold</b>', 'This is bold', true], 382 'Long name' => [str_repeat('a', 100), str_repeat('a', 100), true], 383 'Too long name' => [str_repeat('a', 300), str_repeat('a', 255), true], 384 'Empty name' => ['', 'Test content ', false], 385 'Blanks only' => [' ', 'Test content ', false], 386 'Zero name' => ['0', '0', true], 387 ]; 388 } 389 390 /** 391 * Test the behaviour of rename_content(). 392 * 393 * @dataProvider rename_content_provider 394 * @param string $newname The name to set 395 * @param string $expected The name result 396 * @param bool $result The bolean result expected when renaming 397 * 398 * @covers ::rename_content 399 */ 400 public function test_rename_content(string $newname, string $expected, bool $result) { 401 global $DB; 402 403 $this->resetAfterTest(); 404 405 // Create course and teacher user. 406 $course = $this->getDataGenerator()->create_course(); 407 $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); 408 $coursecontext = \context_course::instance($course->id); 409 $contenttype = new contenttype($coursecontext); 410 411 // Add some content to the content bank as teacher. 412 $this->setUser($teacher); 413 $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); 414 $contents = $generator->generate_contentbank_data('contenttype_testable', 1, $teacher->id); 415 $content = array_shift($contents); 416 417 $oldname = $content->get_name(); 418 419 // Check the content is renamed as expected by a user with permission. 420 $renamed = $contenttype->rename_content($content, $newname); 421 $this->assertEquals($result, $renamed); 422 $record = $DB->get_record('contentbank_content', ['id' => $content->get_id()]); 423 $this->assertEquals($expected, $record->name); 424 } 425 426 /** 427 * Test the behaviour of move_content(). 428 */ 429 public function test_move_content() { 430 global $DB; 431 432 $this->resetAfterTest(); 433 $systemcontext = context_system::instance(); 434 $course = $this->getDataGenerator()->create_course(); 435 $coursecontext = \context_course::instance($course->id); 436 437 // Add some content to the content bank. 438 $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); 439 $systemcontents = $generator->generate_contentbank_data('contenttype_testable', 3, 0, $systemcontext); 440 $generator->generate_contentbank_data('contenttype_testable', 3, 0, $coursecontext); 441 $systemcontent = reset($systemcontents); 442 443 // Check the content has been created as expected. 444 $this->assertEquals(6, $DB->count_records('contentbank_content')); 445 $this->assertEquals(3, $DB->count_records('contentbank_content', ['contextid' => $systemcontext->id])); 446 $this->assertEquals(3, $DB->count_records('contentbank_content', ['contextid' => $coursecontext->id])); 447 448 // Check the content files has been created as expected. 449 $this->assertEquals(12, $DB->count_records('files', ['component' => 'contentbank'])); 450 $this->assertEquals(6, $DB->count_records('files', ['component' => 'contentbank', 'contextid' => $systemcontext->id])); 451 $this->assertEquals(6, $DB->count_records('files', ['component' => 'contentbank', 'contextid' => $coursecontext->id])); 452 453 // Check the content is moved as expected. 454 $contenttype = new contenttype($systemcontext); 455 $this->assertTrue($contenttype->move_content($systemcontent, $coursecontext)); 456 $this->assertEquals(6, $DB->count_records('contentbank_content')); 457 $this->assertEquals(2, $DB->count_records('contentbank_content', ['contextid' => $systemcontext->id])); 458 $this->assertEquals(4, $DB->count_records('contentbank_content', ['contextid' => $coursecontext->id])); 459 460 // Check the content files were moved as expected. 461 $this->assertEquals(12, $DB->count_records('files', ['component' => 'contentbank'])); 462 $this->assertEquals(4, $DB->count_records('files', ['component' => 'contentbank', 'contextid' => $systemcontext->id])); 463 $this->assertEquals(8, $DB->count_records('files', ['component' => 'contentbank', 'contextid' => $coursecontext->id])); 464 } 465 466 /** 467 * Test the behaviour of can_manage(). 468 * 469 * @covers ::can_manage 470 */ 471 public function test_can_manage() { 472 global $DB, $USER; 473 474 $this->resetAfterTest(); 475 $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); 476 477 // Create course and teacher user. 478 $teacherroleid = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']); 479 $course = $this->getDataGenerator()->create_course(); 480 $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); 481 $manager = $this->getDataGenerator()->create_and_enrol($course, 'manager'); 482 $coursecontext = \context_course::instance($course->id); 483 484 $contenttype = new contenttype($coursecontext); 485 486 // Add some content to the content bank as admin. 487 $this->setAdminUser(); 488 $contentsbyadmin = $generator->generate_contentbank_data('contenttype_testable', 1, $USER->id, $coursecontext); 489 $contentbyadmin = array_shift($contentsbyadmin); 490 491 // Add some content to the content bank as teacher. 492 $contentsbyteacher = $generator->generate_contentbank_data('contenttype_testable', 1, $teacher->id, $coursecontext); 493 $contentbyteacher = array_shift($contentsbyteacher); 494 495 // Check the content has been created as expected. 496 $records = $DB->count_records('contentbank_content'); 497 $this->assertEquals(2, $records); 498 499 // Check manager can manage by default all the contents created. 500 $this->setUser($manager); 501 $this->assertTrue($contenttype->can_manage($contentbyteacher)); 502 $this->assertTrue($contenttype->can_manage($contentbyadmin)); 503 504 // Check teacher can only edit their own content. 505 $this->setUser($teacher); 506 $this->assertTrue($contenttype->can_manage($contentbyteacher)); 507 $this->assertFalse($contenttype->can_manage($contentbyadmin)); 508 509 // Unassign capability to teacher role and check they not can not edit any content. 510 unassign_capability('moodle/contentbank:manageowncontent', $teacherroleid); 511 $this->assertFalse($contenttype->can_manage($contentbyteacher)); 512 $this->assertFalse($contenttype->can_manage($contentbyadmin)); 513 } 514 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body