Differences Between: [Versions 400 and 401] [Versions 400 and 402] [Versions 400 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 * Meeting test. 19 * 20 * @package mod_bigbluebuttonbn 21 * @copyright 2018 - present, Blindside Networks Inc 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 * @author Jesus Federico (jesus [at] blindsidenetworks [dt] com) 24 */ 25 26 namespace mod_bigbluebuttonbn; 27 28 use mod_bigbluebuttonbn\test\testcase_helper_trait; 29 30 /** 31 * Meeting tests class. 32 * 33 * @package mod_bigbluebuttonbn 34 * @copyright 2018 - present, Blindside Networks Inc 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 * @author Jesus Federico (jesus [at] blindsidenetworks [dt] com) 37 * @covers \mod_bigbluebuttonbn\meeting 38 * @coversDefaultClass \mod_bigbluebuttonbn\meeting 39 */ 40 class meeting_test extends \advanced_testcase { 41 use testcase_helper_trait; 42 43 /** 44 * Setup Test 45 */ 46 public function setUp(): void { 47 parent::setUp(); 48 $this->initialise_mock_server(); 49 // We do not force the group mode so we can change the activity group mode during test. 50 $this->course = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS]); 51 $this->getDataGenerator()->create_group(['name' => 'G1', 'courseid' => $this->course->id]); 52 $this->getDataGenerator()->create_group(['name' => 'G2', 'courseid' => $this->course->id]); 53 } 54 55 /** 56 * Get a list of possible test (dataprovider) 57 * 58 * @return array[] 59 */ 60 public function get_instance_types_meeting_info(): array { 61 return [ 62 'Instance Type ALL - No Group' => [ 63 'type' => instance::TYPE_ALL, 64 'groupname' => null, 65 'groupmode' => NOGROUPS, 66 'canjoin' => ['useringroup' => true, 'usernotingroup' => true], 67 ], 68 'Instance Type ALL - Group 1 - Visible groups' => [ 69 'type' => instance::TYPE_ALL, 70 'groupname' => 'G1', 71 'groupmode' => VISIBLEGROUPS, 72 'canjoin' => ['useringroup' => true, 'usernotingroup' => true], 73 ], 74 'Instance Type ALL - Group 1 - Separate groups' => [ 75 'type' => instance::TYPE_ALL, 76 'groupname' => 'G1', 77 'groupmode' => SEPARATEGROUPS, 78 'canjoin' => ['useringroup' => true, 'usernotingroup' => false], 79 ], 80 'Instance Type ROOM Only - No Group' => [ 81 'type' => instance::TYPE_ROOM_ONLY, 82 'groupname' => null, 83 'groupmode' => NOGROUPS, 84 'canjoin' => ['useringroup' => true, 'usernotingroup' => true], 85 ], 86 'Instance Type ROOM Only - Group 1 - Visible groups' => [ 87 'type' => instance::TYPE_ROOM_ONLY, 88 'groupname' => 'G1', 89 'groupmode' => VISIBLEGROUPS, 90 'canjoin' => ['useringroup' => true, 'usernotingroup' => true], 91 ], 92 'Instance Type ROOM Only - Group 1 - Separate groups' => [ 93 'type' => instance::TYPE_ROOM_ONLY, 94 'groupname' => 'G1', 95 'groupmode' => SEPARATEGROUPS, 96 'canjoin' => ['useringroup' => true, 'usernotingroup' => false], 97 ], 98 'Instance Type Recording Only - No Group' => [ 99 'type' => instance::TYPE_RECORDING_ONLY, 100 'groupname' => null, 101 'groupmode' => NOGROUPS, 102 'canjoin' => ['useringroup' => false, 'usernotingroup' => false] 103 ], 104 'Instance Type Recording Only - Group 1' => [ 105 'type' => instance::TYPE_RECORDING_ONLY, 106 'groupname' => 'G1', 107 'groupmode' => VISIBLEGROUPS, 108 'canjoin' => ['useringroup' => false, 'usernotingroup' => false] 109 ] 110 ]; 111 } 112 113 /** 114 * Test that create meeing is working for all types. 115 * 116 * @dataProvider get_instance_types_meeting_info 117 * @param int $type 118 * @param string|null $groupname 119 * @covers ::create_meeting 120 * @covers ::create_meeting_data 121 * @covers ::create_meeting_metadata 122 */ 123 public function test_create_meeting(int $type, ?string $groupname) { 124 $this->resetAfterTest(); 125 [$meeting, $useringroup, $usernotingroup, $groupid, $activity] = 126 $this->prepare_meeting($type, $groupname, SEPARATEGROUPS, false); 127 $meeting->create_meeting(); 128 $meetinginfo = $meeting->get_meeting_info(); 129 $this->assertNotNull($meetinginfo); 130 $this->assertEquals($activity->id, $meetinginfo->bigbluebuttonbnid); 131 $this->assertFalse($meetinginfo->statusrunning); 132 $this->assertStringContainsString("is ready", $meetinginfo->statusmessage); 133 $this->assertEquals($groupid, $meetinginfo->groupid); 134 } 135 136 /** 137 * Test for get meeting info for all types 138 * 139 * @param int $type 140 * @param string|null $groupname 141 * @dataProvider get_instance_types_meeting_info 142 * @covers ::get_meeting_info 143 * @covers ::do_get_meeting_info 144 */ 145 public function test_get_meeting_info(int $type, ?string $groupname) { 146 $this->resetAfterTest(); 147 [$meeting, $useringroup, $usernotingroup, $groupid, $activity] = $this->prepare_meeting($type, $groupname); 148 $meetinginfo = $meeting->get_meeting_info(); 149 $this->assertNotNull($meetinginfo); 150 $this->assertEquals($activity->id, $meetinginfo->bigbluebuttonbnid); 151 $this->assertTrue($meetinginfo->statusrunning); 152 $this->assertStringContainsString("in progress", $meetinginfo->statusmessage); 153 $this->assertEquals($groupid, $meetinginfo->groupid); 154 $meeting->end_meeting(); 155 $meeting->update_cache(); 156 $meetinginfo = $meeting->get_meeting_info(); 157 $this->assertFalse($meetinginfo->statusrunning); 158 } 159 160 /** 161 * Test can join is working for all types 162 * 163 * @param int $type 164 * @param string|null $groupname 165 * @param int $groupmode 166 * @param array $canjoin 167 * @dataProvider get_instance_types_meeting_info 168 * @covers ::can_join 169 */ 170 public function test_can_join(int $type, ?string $groupname, int $groupmode, array $canjoin) { 171 $this->resetAfterTest(); 172 [$meeting, $useringroup, $usernotingroup, $groupid, $activity] = $this->prepare_meeting($type, $groupname, $groupmode); 173 $this->setUser($useringroup); 174 $meeting->update_cache(); 175 $this->assertEquals($canjoin['useringroup'], $meeting->can_join()); 176 if ($meeting->can_join()) { 177 $meetinginfo = $meeting->get_meeting_info(); 178 $this->assertStringContainsString("The session is in progress.", $meetinginfo->statusmessage); 179 } 180 if ($groupname) { 181 $this->setUser($usernotingroup); 182 $meeting->update_cache(); 183 $this->assertEquals($canjoin['usernotingroup'], $meeting->can_join()); 184 } 185 } 186 187 /** 188 * Test can join is working if opening/closing time are set 189 * 190 * @param int $type 191 * @param string|null $groupname 192 * @param int $groupmode 193 * @param array $canjoin 194 * @param array $dates 195 * @dataProvider get_data_can_join_with_dates 196 * @covers ::can_join 197 */ 198 public function test_can_join_with_dates(int $type, ?string $groupname, int $groupmode, array $canjoin, array $dates) { 199 // Apply the data provider relative values to now. 200 array_walk($dates, function(&$val) { 201 $val = time() + $val; 202 }); 203 $this->resetAfterTest(); 204 [$meeting, $useringroup, $usernotingroup, $groupid, $activity] = 205 $this->prepare_meeting($type, $groupname, $groupmode, true, $dates); 206 $this->setUser($useringroup); 207 $meeting->update_cache(); 208 $this->assertEquals($canjoin['useringroup'], $meeting->can_join()); 209 // We check that admin can not join outside opening/closing times either. 210 $this->setAdminUser(); 211 $this->assertEquals(false, $meeting->can_join()); 212 if ($groupname) { 213 $this->setUser($usernotingroup); 214 $meeting->update_cache(); 215 $this->assertEquals($canjoin['usernotingroup'], $meeting->can_join()); 216 $this->setAdminUser(); 217 $this->assertEquals(false, $meeting->can_join()); 218 } 219 } 220 221 /** 222 * Test can join is working if the "Wait for moderator to join" setting is set and a moderator has not yet joined. 223 * 224 * @covers ::join 225 * @covers ::join_meeting 226 */ 227 public function test_join_wait_for_moderator_not_joined() { 228 $this->resetAfterTest(); 229 230 $this->setAdminUser(); 231 $bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 232 $student = $this->getDataGenerator()->create_and_enrol($this->get_course()); 233 $meetinginfo = [ 234 'course' => $this->get_course()->id, 235 'type' => instance::TYPE_ALL, 236 'wait' => 1, 237 ]; 238 $activity = $bbbgenerator->create_instance($meetinginfo, [ 239 'wait' => 1, 240 ]); 241 $instance = instance::get_from_instanceid($activity->id); 242 $meeting = new meeting($instance); 243 244 // The moderator has not joined. 245 $this->setUser($student); 246 $meeting->update_cache(); 247 $this->expectException(\mod_bigbluebuttonbn\local\exceptions\meeting_join_exception::class); 248 meeting::join_meeting($instance); 249 } 250 251 /** 252 * Test can join is working if the "Wait for moderator to join" setting is set and a moderator has already joined. 253 * 254 * @covers ::join 255 * @covers ::join_meeting 256 */ 257 public function test_join_wait_for_moderator_is_joined() { 258 $this->resetAfterTest(); 259 260 $this->setAdminUser(); 261 $bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 262 $moderator = $this->getDataGenerator()->create_and_enrol($this->get_course(), 'editingteacher'); 263 $student = $this->getDataGenerator()->create_and_enrol($this->get_course()); 264 $meetinginfo = [ 265 'course' => $this->get_course()->id, 266 'type' => instance::TYPE_ALL, 267 'wait' => 1, 268 'moderators' => 'role:editingteacher', 269 ]; 270 $activity = $bbbgenerator->create_instance($meetinginfo, [ 271 'wait' => 1, 272 ]); 273 $instance = instance::get_from_instanceid($activity->id); 274 $meeting = new meeting($instance); 275 $bbbgenerator->create_meeting([ 276 'instanceid' => $instance->get_instance_id(), 277 ]); 278 279 $this->setUser($moderator); 280 $meeting->update_cache(); 281 $joinurl = $meeting->join(logger::ORIGIN_BASE); 282 $this->assertIsString($joinurl); 283 $this->join_meeting($joinurl); 284 $meeting->update_cache(); 285 $this->assertCount(1, $meeting->get_attendees()); 286 287 // The student can now join the meeting as a moderator is present. 288 $this->setUser($student); 289 $joinurl = $meeting->join(logger::ORIGIN_BASE); 290 $this->assertIsString($joinurl); 291 } 292 293 /** 294 * Test can join is working if the "user limit" setting is set and reached. 295 * 296 * @covers ::join 297 * @covers ::join_meeting 298 */ 299 public function test_join_user_limit_reached() { 300 $this->resetAfterTest(); 301 set_config('bigbluebuttonbn_userlimit_editable', true); 302 $this->setAdminUser(); 303 $bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 304 $moderator = $this->getDataGenerator()->create_and_enrol($this->get_course(), 'editingteacher'); 305 $student1 = $this->getDataGenerator()->create_and_enrol($this->get_course()); 306 $student2 = $this->getDataGenerator()->create_and_enrol($this->get_course()); 307 $meetinginfo = [ 308 'course' => $this->get_course()->id, 309 'type' => instance::TYPE_ALL, 310 'userlimit' => 2, 311 ]; 312 $activity = $bbbgenerator->create_instance($meetinginfo, [ 313 'userlimit' => 2, 314 ]); 315 $instance = instance::get_from_instanceid($activity->id); 316 $meeting = new meeting($instance); 317 $bbbgenerator->create_meeting([ 318 'instanceid' => $instance->get_instance_id(), 319 ]); 320 // Moderator joins the meeting. 321 $this->setUser($moderator); 322 $this->join_meeting($meeting->join(logger::ORIGIN_BASE)); 323 $meeting->update_cache(); 324 $this->assertEquals(1, $meeting->get_participant_count()); 325 326 // Student1 joins the meeting. 327 $this->setUser($student1); 328 $this->join_meeting($meeting->join(logger::ORIGIN_BASE)); 329 $meeting->update_cache(); 330 $this->assertEquals(2, $meeting->get_participant_count()); 331 $this->assertTrue($instance->has_user_limit_been_reached($meeting->get_participant_count())); 332 333 // Student2 tries to join but the limit has been reached. 334 $this->setUser($student2); 335 $meeting->update_cache(); 336 $this->assertFalse($meeting->can_join()); 337 $this->expectException(\mod_bigbluebuttonbn\local\exceptions\meeting_join_exception::class); 338 meeting::join_meeting($instance); 339 } 340 341 /** 342 * Test that attendees returns the right list of attendees 343 * 344 * @covers ::get_attendees 345 */ 346 public function test_get_attendees() { 347 $this->resetAfterTest(); 348 [$meeting, $useringroup, $usernotingroup, $groupid, $activity] = 349 $this->prepare_meeting(instance::TYPE_ALL, null, NOGROUPS, true); 350 $this->setUser($useringroup); 351 $this->join_meeting($meeting->join(logger::ORIGIN_BASE)); 352 $meeting->update_cache(); 353 $this->assertCount(1, $meeting->get_attendees()); 354 $otheruser = $this->getDataGenerator()->create_and_enrol($this->get_course()); 355 $this->setUser($otheruser); 356 $meeting->update_cache(); 357 $this->join_meeting($meeting->join(logger::ORIGIN_BASE)); 358 $meeting->update_cache(); 359 $this->assertCount(2, $meeting->get_attendees()); 360 } 361 362 /** 363 * Test that attendees returns the right list of attendees 364 * 365 * @covers ::get_attendees 366 */ 367 public function test_participant_count() { 368 $this->resetAfterTest(); 369 [$meeting, $useringroup, $usernotingroup, $groupid, $activity] = 370 $this->prepare_meeting(instance::TYPE_ALL, null, NOGROUPS, true); 371 $this->setUser($useringroup); 372 $this->join_meeting($meeting->join(logger::ORIGIN_BASE)); 373 $meeting->update_cache(); 374 $meetinginfo = $meeting->get_meeting_info(); 375 $this->assertEquals(1, $meetinginfo->participantcount); 376 $this->assertEquals(1, $meetinginfo->totalusercount); 377 $this->assertEquals(0, $meetinginfo->moderatorcount); 378 $this->setUser($usernotingroup); 379 $this->join_meeting($meeting->join(logger::ORIGIN_BASE)); 380 $meeting->update_cache(); 381 $meetinginfo = $meeting->get_meeting_info(); 382 $this->assertEquals(2, $meetinginfo->participantcount); 383 $this->assertEquals(2, $meetinginfo->totalusercount); 384 $this->assertEquals(0, $meetinginfo->moderatorcount); 385 $this->setAdminUser(); 386 $this->join_meeting($meeting->join(logger::ORIGIN_BASE)); 387 $meeting->update_cache(); 388 $meetinginfo = $meeting->get_meeting_info(); 389 $this->assertEquals(2, $meetinginfo->participantcount); 390 $this->assertEquals(3, $meetinginfo->totalusercount); 391 $this->assertEquals(1, $meetinginfo->moderatorcount); 392 } 393 /** 394 * Send a join meeting API CALL 395 * 396 * @param string $url 397 */ 398 protected function join_meeting(string $url) { 399 $curl = new \curl(); 400 $url = new \moodle_url($url); 401 $curl->get($url->out_omit_querystring(), $url->params()); 402 } 403 404 /** 405 * Get a list of possible test (dataprovider) 406 * 407 * @return array[] 408 */ 409 public function get_data_can_join_with_dates(): array { 410 return [ 411 'Instance Type ALL - No Group - Closed in past' => [ 412 'type' => instance::TYPE_ALL, 413 'groupname' => null, 414 'groupmode' => NOGROUPS, 415 'canjoin' => ['useringroup' => false, 'usernotingroup' => false], 416 'dates' => ['openingtime' => -7200, 'closingtime' => -3600] 417 ], 418 'Instance Type ALL - No Group - Open in future' => [ 419 'type' => instance::TYPE_ALL, 420 'groupname' => null, 421 'groupmode' => NOGROUPS, 422 'canjoin' => ['useringroup' => false, 'usernotingroup' => false], 423 'dates' => ['openingtime' => 3600, 'closingtime' => 7200] 424 ], 425 ]; 426 } 427 428 /** 429 * Helper to prepare for a meeting 430 * 431 * @param int $type 432 * @param string|null $groupname 433 * @param int $groupmode 434 * @param bool $createmeeting 435 * @param array $dates 436 * @return array 437 */ 438 protected function prepare_meeting(int $type, ?string $groupname, int $groupmode = SEPARATEGROUPS, bool $createmeeting = true, 439 array $dates = []) { 440 $this->setAdminUser(); 441 $bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 442 $groupid = 0; 443 $useringroup = $this->getDataGenerator()->create_and_enrol($this->get_course()); 444 $usernotingroup = $this->getDataGenerator()->create_and_enrol($this->get_course()); 445 if (!empty($groupname)) { 446 $groupid = groups_get_group_by_name($this->get_course()->id, $groupname); 447 $this->getDataGenerator()->create_group_member(['groupid' => $groupid, 'userid' => $useringroup->id]); 448 } 449 $meetinginfo = [ 450 'course' => $this->get_course()->id, 451 'type' => $type 452 ]; 453 if ($dates) { 454 $meetinginfo = array_merge($meetinginfo, $dates); 455 }; 456 $activity = $bbbgenerator->create_instance($meetinginfo, ['groupmode' => $groupmode]); 457 $instance = instance::get_from_instanceid($activity->id); 458 if ($groupid) { 459 $instance->set_group_id($groupid); 460 } 461 if ($createmeeting) { 462 // Create the meetings on the mock server, so we can join it as a simple user. 463 $bbbgenerator->create_meeting([ 464 'instanceid' => $instance->get_instance_id(), 465 'groupid' => $instance->get_group_id() 466 ]); 467 } 468 $meeting = new meeting($instance); 469 return [$meeting, $useringroup, $usernotingroup, $groupid, $activity]; 470 } 471 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body