See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 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 * Unit tests for mod_lti lib 19 * 20 * @package mod_lti 21 * @category external 22 * @copyright 2015 Juan Leyva <juan@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 * @since Moodle 3.0 25 */ 26 namespace mod_lti; 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 /** 31 * Unit tests for mod_lti lib 32 * 33 * @package mod_lti 34 * @category external 35 * @copyright 2015 Juan Leyva <juan@moodle.com> 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 * @since Moodle 3.0 38 */ 39 class lib_test extends \advanced_testcase { 40 41 /** 42 * Prepares things before this test case is initialised 43 * @return void 44 */ 45 public static function setUpBeforeClass(): void { 46 global $CFG; 47 require_once($CFG->dirroot . '/mod/lti/lib.php'); 48 } 49 50 /** 51 * Test lti_view 52 * @return void 53 */ 54 public function test_lti_view() { 55 global $CFG; 56 57 $CFG->enablecompletion = 1; 58 $this->resetAfterTest(); 59 60 $this->setAdminUser(); 61 // Setup test data. 62 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 63 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id), 64 array('completion' => 2, 'completionview' => 1)); 65 $context = \context_module::instance($lti->cmid); 66 $cm = get_coursemodule_from_instance('lti', $lti->id); 67 68 // Trigger and capture the event. 69 $sink = $this->redirectEvents(); 70 71 lti_view($lti, $course, $cm, $context); 72 73 $events = $sink->get_events(); 74 // 2 additional events thanks to completion. 75 $this->assertCount(3, $events); 76 $event = array_shift($events); 77 78 // Checking that the event contains the expected values. 79 $this->assertInstanceOf('\mod_lti\event\course_module_viewed', $event); 80 $this->assertEquals($context, $event->get_context()); 81 $moodleurl = new \moodle_url('/mod/lti/view.php', array('id' => $cm->id)); 82 $this->assertEquals($moodleurl, $event->get_url()); 83 $this->assertEventContextNotUsed($event); 84 $this->assertNotEmpty($event->get_name()); 85 86 // Check completion status. 87 $completion = new \completion_info($course); 88 $completiondata = $completion->get_data($cm); 89 $this->assertEquals(1, $completiondata->completionstate); 90 91 } 92 93 /** 94 * Test deleting LTI instance. 95 */ 96 public function test_lti_delete_instance() { 97 $this->resetAfterTest(); 98 99 $this->setAdminUser(); 100 $course = $this->getDataGenerator()->create_course(array()); 101 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 102 $cm = get_coursemodule_from_instance('lti', $lti->id); 103 104 // Must not throw notices. 105 course_delete_module($cm->id); 106 } 107 108 public function test_lti_core_calendar_provide_event_action() { 109 $this->resetAfterTest(); 110 $this->setAdminUser(); 111 112 // Create the activity. 113 $course = $this->getDataGenerator()->create_course(); 114 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 115 116 // Create a calendar event. 117 $event = $this->create_action_event($course->id, $lti->id, 118 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 119 120 // Create an action factory. 121 $factory = new \core_calendar\action_factory(); 122 123 // Decorate action event. 124 $actionevent = mod_lti_core_calendar_provide_event_action($event, $factory); 125 126 // Confirm the event was decorated. 127 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 128 $this->assertEquals(get_string('view'), $actionevent->get_name()); 129 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 130 $this->assertEquals(1, $actionevent->get_item_count()); 131 $this->assertTrue($actionevent->is_actionable()); 132 } 133 134 public function test_lti_core_calendar_provide_event_action_as_non_user() { 135 global $CFG; 136 137 $this->resetAfterTest(); 138 $this->setAdminUser(); 139 140 // Create the activity. 141 $course = $this->getDataGenerator()->create_course(); 142 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 143 144 // Create a calendar event. 145 $event = $this->create_action_event($course->id, $lti->id, 146 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 147 148 // Now, log out. 149 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 150 $this->setUser(); 151 152 // Create an action factory. 153 $factory = new \core_calendar\action_factory(); 154 155 // Decorate action event. 156 $actionevent = mod_lti_core_calendar_provide_event_action($event, $factory); 157 158 // Confirm the event is not shown at all. 159 $this->assertNull($actionevent); 160 } 161 162 public function test_lti_core_calendar_provide_event_action_for_user() { 163 global $CFG; 164 165 $this->resetAfterTest(); 166 $this->setAdminUser(); 167 168 // Create the activity. 169 $course = $this->getDataGenerator()->create_course(); 170 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 171 172 // Enrol a student in the course. 173 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 174 175 // Create a calendar event. 176 $event = $this->create_action_event($course->id, $lti->id, 177 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 178 179 // Now, log out. 180 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 181 $this->setUser(); 182 183 // Create an action factory. 184 $factory = new \core_calendar\action_factory(); 185 186 // Decorate action event for the student. 187 $actionevent = mod_lti_core_calendar_provide_event_action($event, $factory, $student->id); 188 189 // Confirm the event was decorated. 190 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 191 $this->assertEquals(get_string('view'), $actionevent->get_name()); 192 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 193 $this->assertEquals(1, $actionevent->get_item_count()); 194 $this->assertTrue($actionevent->is_actionable()); 195 } 196 197 public function test_lti_core_calendar_provide_event_action_already_completed() { 198 global $CFG; 199 200 $this->resetAfterTest(); 201 $this->setAdminUser(); 202 203 $CFG->enablecompletion = 1; 204 205 // Create the activity. 206 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 207 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id), 208 array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS)); 209 210 // Get some additional data. 211 $cm = get_coursemodule_from_instance('lti', $lti->id); 212 213 // Create a calendar event. 214 $event = $this->create_action_event($course->id, $lti->id, 215 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 216 217 // Mark the activity as completed. 218 $completion = new \completion_info($course); 219 $completion->set_module_viewed($cm); 220 221 // Create an action factory. 222 $factory = new \core_calendar\action_factory(); 223 224 // Decorate action event. 225 $actionevent = mod_lti_core_calendar_provide_event_action($event, $factory); 226 227 // Ensure result was null. 228 $this->assertNull($actionevent); 229 } 230 231 public function test_lti_core_calendar_provide_event_action_already_completed_as_non_user() { 232 global $CFG; 233 234 $this->resetAfterTest(); 235 $this->setAdminUser(); 236 237 $CFG->enablecompletion = 1; 238 239 // Create the activity. 240 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 241 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id), 242 array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS)); 243 244 // Get some additional data. 245 $cm = get_coursemodule_from_instance('lti', $lti->id); 246 247 // Create a calendar event. 248 $event = $this->create_action_event($course->id, $lti->id, 249 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 250 251 // Mark the activity as completed. 252 $completion = new \completion_info($course); 253 $completion->set_module_viewed($cm); 254 255 // Now, log out. 256 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 257 $this->setUser(); 258 259 // Create an action factory. 260 $factory = new \core_calendar\action_factory(); 261 262 // Decorate action event. 263 $actionevent = mod_lti_core_calendar_provide_event_action($event, $factory); 264 265 // Ensure result was null. 266 $this->assertNull($actionevent); 267 } 268 269 public function test_lti_core_calendar_provide_event_action_already_completed_for_user() { 270 global $CFG; 271 272 $this->resetAfterTest(); 273 $this->setAdminUser(); 274 275 $CFG->enablecompletion = 1; 276 277 // Create the activity. 278 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 279 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id), 280 array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS)); 281 282 // Enrol 2 students in the course. 283 $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 284 $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 285 286 // Get some additional data. 287 $cm = get_coursemodule_from_instance('lti', $lti->id); 288 289 // Create a calendar event. 290 $event = $this->create_action_event($course->id, $lti->id, 291 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 292 293 // Mark the activity as completed for $student1. 294 $completion = new \completion_info($course); 295 $completion->set_module_viewed($cm, $student1->id); 296 297 // Now, log in as $student2. 298 $this->setUser($student2); 299 300 // Create an action factory. 301 $factory = new \core_calendar\action_factory(); 302 303 // Decorate action event for $student1. 304 $actionevent = mod_lti_core_calendar_provide_event_action($event, $factory, $student1->id); 305 306 // Ensure result was null. 307 $this->assertNull($actionevent); 308 } 309 310 /** 311 * Creates an action event. 312 * 313 * @param int $courseid The course id. 314 * @param int $instanceid The instance id. 315 * @param string $eventtype The event type. 316 * @return bool|calendar_event 317 */ 318 private function create_action_event($courseid, $instanceid, $eventtype) { 319 $event = new \stdClass(); 320 $event->name = 'Calendar event'; 321 $event->modulename = 'lti'; 322 $event->courseid = $courseid; 323 $event->instance = $instanceid; 324 $event->type = CALENDAR_EVENT_TYPE_ACTION; 325 $event->eventtype = $eventtype; 326 $event->timestart = time(); 327 328 return \calendar_event::create($event); 329 } 330 331 /** 332 * Test verifying the output of the lti_get_course_content_items and lti_get_all_content_items callbacks. 333 */ 334 public function test_content_item_callbacks() { 335 $this->resetAfterTest(); 336 global $DB, $CFG; 337 require_once($CFG->dirroot . '/mod/lti/locallib.php'); 338 339 $admin = get_admin(); 340 $time = time(); 341 $course = $this->getDataGenerator()->create_course(); 342 $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); 343 $course2 = $this->getDataGenerator()->create_course(); 344 $teacher2 = $this->getDataGenerator()->create_and_enrol($course2, 'editingteacher'); 345 346 // Create some preconfigured tools. 347 $sitetoolrecord = (object) [ 348 'name' => 'Site level tool which is available in the activity chooser', 349 'baseurl' => 'http://example.com', 350 'createdby' => $admin->id, 351 'course' => SITEID, 352 'ltiversion' => 'LTI-1p0', 353 'timecreated' => $time, 354 'timemodified' => $time, 355 'state' => LTI_TOOL_STATE_CONFIGURED, 356 'coursevisible' => LTI_COURSEVISIBLE_ACTIVITYCHOOSER 357 ]; 358 $sitetoolrecordnonchooser = (object) [ 359 'name' => 'Site level tool which is NOT available in the course activity chooser', 360 'baseurl' => 'http://example2.com', 361 'createdby' => $admin->id, 362 'course' => SITEID, 363 'ltiversion' => 'LTI-1p0', 364 'timecreated' => $time, 365 'timemodified' => $time, 366 'state' => LTI_TOOL_STATE_CONFIGURED, 367 'coursevisible' => LTI_COURSEVISIBLE_PRECONFIGURED 368 ]; 369 $course1toolrecord = (object) [ 370 'name' => 'Course created tool which is available in the activity chooser', 371 'baseurl' => 'http://example3.com', 372 'createdby' => $teacher->id, 373 'course' => $course->id, 374 'ltiversion' => 'LTI-1p0', 375 'timecreated' => $time, 376 'timemodified' => $time, 377 'state' => LTI_TOOL_STATE_CONFIGURED, 378 'coursevisible' => LTI_COURSEVISIBLE_ACTIVITYCHOOSER 379 ]; 380 $course2toolrecord = (object) [ 381 'name' => 'Course created tool which is available in the activity chooser', 382 'baseurl' => 'http://example4.com', 383 'createdby' => $teacher2->id, 384 'course' => $course2->id, 385 'ltiversion' => 'LTI-1p0', 386 'timecreated' => $time, 387 'timemodified' => $time, 388 'state' => LTI_TOOL_STATE_CONFIGURED, 389 'coursevisible' => LTI_COURSEVISIBLE_ACTIVITYCHOOSER 390 ]; 391 $tool1id = $DB->insert_record('lti_types', $sitetoolrecord); 392 $tool2id = $DB->insert_record('lti_types', $sitetoolrecordnonchooser); 393 $tool3id = $DB->insert_record('lti_types', $course1toolrecord); 394 $tool4id = $DB->insert_record('lti_types', $course2toolrecord); 395 $sitetoolrecord->id = $tool1id; 396 $sitetoolrecordnonchooser->id = $tool2id; 397 $course1toolrecord->id = $tool3id; 398 $course2toolrecord->id = $tool4id; 399 400 $defaultmodulecontentitem = new \core_course\local\entity\content_item( 401 '1', 402 'default module content item', 403 new \core_course\local\entity\string_title('Content item title'), 404 new \moodle_url(''), 405 'icon', 406 'Description of the module', 407 MOD_ARCHETYPE_OTHER, 408 'mod_lti', 409 MOD_PURPOSE_CONTENT 410 ); 411 412 // The lti_get_lti_types_by_course method (used by the callbacks) assumes the global user. 413 $this->setUser($teacher); 414 415 // Teacher in course1 should be able to see the default module item ('external tool'), 416 // the site preconfigured tool and the tool created in course1. 417 $courseitems = lti_get_course_content_items($defaultmodulecontentitem, $teacher, $course); 418 $this->assertCount(3, $courseitems); 419 $ids = []; 420 foreach ($courseitems as $item) { 421 $ids[] = $item->get_id(); 422 } 423 $this->assertContains(1, $ids); 424 $this->assertContains($sitetoolrecord->id + 1, $ids); 425 $this->assertContains($course1toolrecord->id + 1, $ids); 426 $this->assertNotContains($sitetoolrecordnonchooser->id + 1, $ids); 427 428 // The content items for teacher2 in course2 include the default module content item ('external tool'), 429 // the site preconfigured tool and the tool created in course2. 430 $this->setUser($teacher2); 431 $course2items = lti_get_course_content_items($defaultmodulecontentitem, $teacher2, $course2); 432 $this->assertCount(3, $course2items); 433 $ids = []; 434 foreach ($course2items as $item) { 435 $ids[] = $item->get_id(); 436 } 437 $this->assertContains(1, $ids); 438 $this->assertContains($sitetoolrecord->id + 1, $ids); 439 $this->assertContains($course2toolrecord->id + 1, $ids); 440 $this->assertNotContains($sitetoolrecordnonchooser->id + 1, $ids); 441 442 // When fetching all content items, we expect to see all items available in activity choosers (in any course), 443 // plus the default module content item ('external tool'). 444 $this->setAdminUser(); 445 $allitems = mod_lti_get_all_content_items($defaultmodulecontentitem); 446 $this->assertCount(4, $allitems); 447 $ids = []; 448 foreach ($allitems as $item) { 449 $ids[] = $item->get_id(); 450 } 451 $this->assertContains(1, $ids); 452 $this->assertContains($sitetoolrecord->id + 1, $ids); 453 $this->assertContains($course1toolrecord->id + 1, $ids); 454 $this->assertContains($course2toolrecord->id + 1, $ids); 455 $this->assertNotContains($sitetoolrecordnonchooser->id + 1, $ids); 456 } 457 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body