See Release Notes
Long Term Support Release
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 namespace mod_bigbluebuttonbn\completion; 18 19 use completion_info; 20 use context_module; 21 use mod_bigbluebuttonbn\instance; 22 use mod_bigbluebuttonbn\local\config; 23 use mod_bigbluebuttonbn\logger; 24 use mod_bigbluebuttonbn\meeting; 25 use mod_bigbluebuttonbn\test\testcase_helper_trait; 26 27 /** 28 * Tests for Big Blue Button Completion. 29 * 30 * @package mod_bigbluebuttonbn 31 * @copyright 2021 - present, Blindside Networks Inc 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 * @author Laurent David (laurent@call-learning.fr) 34 * @covers \mod_bigbluebuttonbn\completion\custom_completion 35 */ 36 class completion_test extends \advanced_testcase { 37 use testcase_helper_trait; 38 39 /** 40 * Setup basic 41 */ 42 public function setUp(): void { 43 parent::setUp(); 44 $this->initialise_mock_server(); 45 set_config('enablecompletion', true); // Enable completion for all tests. 46 } 47 48 /** 49 * Completion with no rules: the completion is completed as soons as we view the course. 50 */ 51 public function test_get_completion_state_no_rules() { 52 $this->resetAfterTest(); 53 list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance(); 54 55 $user = $this->getDataGenerator()->create_user(); 56 $this->setUser($user); 57 58 $completion = new custom_completion($bbactivitycm, $user->id); 59 $result = $completion->get_overall_completion_state(); 60 // No custom rules so complete by default. 61 $this->assertEquals(COMPLETION_COMPLETE, $result); 62 } 63 64 /** 65 * Completion with no rules and join meeting 66 */ 67 public function test_get_completion_state_no_rules_and_join_meeting() { 68 $this->resetAfterTest(); 69 list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance(); 70 71 $user = $this->getDataGenerator()->create_user(); 72 $this->setUser($user); 73 74 // Now create a couple of logs. 75 $instance = instance::get_from_instanceid($bbactivity->id); 76 logger::log_meeting_joined_event($instance, 0); 77 // No custom rules and we joined once so complete. 78 $completion = new custom_completion($bbactivitycm, $user->id); 79 $result = $completion->get_overall_completion_state(); 80 $this->assertEquals(COMPLETION_COMPLETE, $result); 81 } 82 83 /** 84 * With state incomplete 85 */ 86 public function test_get_completion_state_incomplete() { 87 $this->resetAfterTest(); 88 89 list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance(); 90 91 $bbactivitycm->override_customdata('customcompletionrules', [ 92 'completionengagementchats' => '1', 93 'completionattendance' => '1' 94 ]); 95 96 $user = $this->getDataGenerator()->create_user(); 97 $this->setUser($user); 98 99 $completion = new custom_completion($bbactivitycm, $user->id); 100 $result = $completion->get_overall_completion_state(); 101 $this->assertEquals(COMPLETION_INCOMPLETE, $result); 102 } 103 104 /** 105 * With state complete 106 */ 107 public function test_get_completion_state_complete() { 108 $this->resetAfterTest(); 109 110 list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance( 111 $this->get_course(), 112 [ 113 'completion' => '2', 114 'completionengagementtalks' => 2, 115 'completionengagementchats' => 2, 116 'completionattendance' => 15 117 ] 118 ); 119 $instance = instance::get_from_instanceid($bbactivity->id); 120 121 $user = $this->getDataGenerator()->create_user(); 122 $this->setUser($user); 123 124 // Add a couple of fake logs. 125 $overrides = ['meetingid' => $bbactivity->meetingid]; 126 $meta = [ 127 'origin' => 0, 128 'data' => [ 129 'duration' => 300, // 300 seconds, i.e 5 mins. 130 'engagement' => [ 131 'chats' => 2, 132 'talks' => 2, 133 ], 134 ], 135 ]; 136 137 // We setup a couple of logs as per engagement and duration. 138 logger::log_event_summary($instance, $overrides, $meta); 139 logger::log_event_summary($instance, $overrides, $meta); 140 $completion = new custom_completion($bbactivitycm, $user->id); 141 $result = $completion->get_overall_completion_state(); 142 $this->assertEquals(COMPLETION_INCOMPLETE, $result); 143 144 // Now we have 15 mins. 145 logger::log_event_summary($instance, $overrides, $meta); 146 // Now that the meeting was joined, it should be complete. 147 $completion = new custom_completion($bbactivitycm, $user->id); 148 $result = $completion->get_overall_completion_state(); 149 $this->assertEquals(COMPLETION_COMPLETE, $result); 150 } 151 152 /** 153 * No rule description but active 154 */ 155 public function test_mod_bigbluebuttonbn_get_completion_active_rule_descriptions() { 156 $this->resetAfterTest(); 157 $user = $this->getDataGenerator()->create_user(); 158 $this->setUser($user); 159 // Two activities, both with automatic completion. One has the 'completionsubmit' rule, one doesn't. 160 // Inspired from the same test in forum. 161 list($bbactivitycontext, $cm1, $bbactivity) = $this->create_instance($this->get_course(), 162 ['completion' => '2']); 163 $cm1->override_customdata('customcompletionrules', [ 164 'completionattendance' => '1' 165 ]); 166 list($bbactivitycontext, $cm2, $bbactivity) = $this->create_instance($this->get_course(), 167 ['completion' => '2']); 168 $cm2->override_customdata('customcompletionrules', [ 169 'completionattendance' => '0' 170 ]); 171 172 $completioncm1 = new custom_completion($cm1, $user->id); 173 // TODO: check the return value here as there might be an issue with the function compared to the forum for example. 174 $this->assertEquals( 175 [ 176 'completionengagementchats' => get_string('completionengagementchats_desc', 'mod_bigbluebuttonbn', 1), 177 'completionengagementtalks' => get_string('completionengagementtalks_desc', 'mod_bigbluebuttonbn', 1), 178 'completionattendance' => get_string('completionattendance_desc', 'mod_bigbluebuttonbn', 1), 179 'completionengagementraisehand' => get_string('completionengagementraisehand_desc', 'mod_bigbluebuttonbn', 1), 180 'completionengagementpollvotes' => get_string('completionengagementpollvotes_desc', 'mod_bigbluebuttonbn', 1), 181 'completionengagementemojis' => get_string('completionengagementemojis_desc', 'mod_bigbluebuttonbn', 1) 182 ], 183 $completioncm1->get_custom_rule_descriptions()); 184 $completioncm2 = new custom_completion($cm2, $user->id); 185 $this->assertEquals( 186 [ 187 'completionengagementchats' => get_string('completionengagementchats_desc', 'mod_bigbluebuttonbn', 1), 188 'completionengagementtalks' => get_string('completionengagementtalks_desc', 'mod_bigbluebuttonbn', 1), 189 'completionattendance' => get_string('completionattendance_desc', 'mod_bigbluebuttonbn', 0), 190 'completionengagementraisehand' => get_string('completionengagementraisehand_desc', 'mod_bigbluebuttonbn', 1), 191 'completionengagementpollvotes' => get_string('completionengagementpollvotes_desc', 'mod_bigbluebuttonbn', 1), 192 'completionengagementemojis' => get_string('completionengagementemojis_desc', 'mod_bigbluebuttonbn', 1) 193 ], $completioncm2->get_custom_rule_descriptions()); 194 } 195 196 /** 197 * Completion View 198 */ 199 public function test_view() { 200 $this->resetAfterTest(); 201 $this->setAdminUser(); 202 list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance( 203 null, ['completion' => 2, 'completionview' => 1] 204 ); 205 206 // Trigger and capture the event. 207 $sink = $this->redirectEvents(); 208 209 // Check completion before viewing. 210 $completion = new completion_info($this->get_course()); 211 $completiondata = $completion->get_data($bbactivitycm); 212 $this->assertEquals(0, $completiondata->viewed); 213 $this->assertEquals(COMPLETION_NOT_VIEWED, $completiondata->completionstate); 214 215 bigbluebuttonbn_view($bbactivity, $this->get_course(), $bbactivitycm, context_module::instance($bbactivitycm->id)); 216 217 $events = $sink->get_events(); 218 $this->assertTrue(count($events) > 1); // TODO : Here we have the module completion event triggered twice. 219 // this might be a bug from 4.0 core and will need some further investigation. 220 $event = reset($events); 221 222 // Checking that the event contains the expected values. 223 $this->assertInstanceOf('\mod_bigbluebuttonbn\event\course_module_viewed', $event); 224 $this->assertEquals($bbactivitycontext, $event->get_context()); 225 $url = new \moodle_url('/mod/bigbluebuttonbn/view.php', ['id' => $bbactivitycontext->instanceid]); 226 $this->assertEquals($url, $event->get_url()); 227 $this->assertEventContextNotUsed($event); 228 $this->assertNotEmpty($event->get_name()); 229 230 // Check completion status. 231 $completion = new completion_info($this->get_course()); 232 $completiondata = $completion->get_data($bbactivitycm); 233 $this->assertEquals(1, $completiondata->viewed); 234 $this->assertEquals(COMPLETION_COMPLETE, $completiondata->completionstate); 235 } 236 237 /** 238 * Completion with no rules and join meeting 239 * 240 * @param array $customcompletionrules 241 * @param array $events 242 * @param int $expectedstate 243 * @dataProvider custom_completion_data_provider 244 */ 245 public function test_get_completion_with_events(array $customcompletionrules, array $events, int $expectedstate) { 246 $this->resetAfterTest(); 247 list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance( 248 $this->get_course(), 249 [ 250 'completion' => '2', 251 ] 252 ); 253 $bbactivitycm->override_customdata('customcompletionrules', $customcompletionrules); 254 $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 255 256 $user = $this->getDataGenerator()->create_user(); 257 $this->setUser($user); 258 259 // Now create a couple of events. 260 $instance = instance::get_from_instanceid($bbactivity->id); 261 set_config('bigbluebuttonbn_meetingevents_enabled', true); 262 $meeting = $plugingenerator->create_meeting([ 263 'instanceid' => $instance->get_instance_id(), 264 'groupid' => $instance->get_group_id(), 265 'participants' => json_encode([$user->id]) 266 ]); 267 foreach ($events as $edesc) { 268 $plugingenerator->add_meeting_event($user, $instance, $edesc->name, $edesc->data ?? ''); 269 } 270 $result = $plugingenerator->send_all_events($instance); 271 $this->assertNotEmpty($result->data); 272 $data = json_decode(json_encode($result->data)); 273 meeting::meeting_events($instance, $data); 274 $completion = new custom_completion($bbactivitycm, $user->id); 275 $result = $completion->get_overall_completion_state(); 276 $this->assertEquals($expectedstate, $result); 277 } 278 279 /** 280 * Data generator 281 * 282 * @return array[] 283 */ 284 public function custom_completion_data_provider() { 285 return [ 286 'simple' => [ 287 'customcompletionrules' => [ 288 'completionengagementtalks' => 1, 289 'completionengagementchats' => 1, 290 ], 291 'events' => [ 292 (object) ['name' => 'talks'], 293 (object) ['name' => 'chats'] 294 ], 295 'expectedstate' => COMPLETION_COMPLETE 296 ], 297 'not right events' => [ 298 'customcompletionrules' => [ 299 'completionengagementchats' => 1, 300 ], 301 'events' => [ 302 (object) ['name' => 'talks'] 303 ], 304 'expectedstate' => COMPLETION_INCOMPLETE 305 ], 306 'attendance' => [ 307 'customcompletionrules' => [ 308 'completionattendance' => 1, 309 ], 310 'events' => [ 311 (object) ['name' => 'talks'], 312 (object) ['name' => 'attendance', 'data' => '70'] 313 ], 314 'expectedstate' => COMPLETION_COMPLETE 315 ] 316 ]; 317 } 318 } 319
title
Description
Body
title
Description
Body
title
Description
Body
title
Body