Differences Between: [Versions 400 and 403] [Versions 401 and 403] [Versions 402 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 * Tests for the Big Blue Button Instance. 18 * 19 * @package mod_bigbluebuttonbn 20 * @copyright 2021 Andrew Lyons <andrew@nicols.co.uk> 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 */ 23 24 namespace mod_bigbluebuttonbn; 25 26 use advanced_testcase; 27 use moodle_exception; 28 29 /** 30 * Tests for the Big Blue Button Instance. 31 * 32 * @package mod_bigbluebuttonbn 33 * @copyright 2021 Andrew Lyons <andrew@nicols.co.uk> 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 * @coversDefaultClass \mod_bigbluebuttonbn\instance 36 */ 37 class instance_test extends advanced_testcase { 38 39 /** 40 * Test get from 41 * 42 * @param string $function 43 * @param string $field 44 * @dataProvider get_from_location_provider 45 * @covers ::get_from_instanceid 46 * @covers ::get_from_cmid 47 */ 48 public function test_get_from(string $function, string $field): void { 49 $this->resetAfterTest(); 50 51 [ 52 'record' => $record, 53 ] = $this->get_test_instance(); 54 55 $instance = call_user_func("mod_bigbluebuttonbn\instance::{$function}", $record->{$field}); 56 57 $this->assertInstanceOf(instance::class, $instance); 58 $this->assertEquals($record->id, $instance->get_instance_id()); 59 $this->assertEquals($record->cmid, $instance->get_cm_id()); 60 $this->assertEquals($record->cmid, $instance->get_cm()->id); 61 } 62 63 /** 64 * Get from location provider 65 * 66 * @return string[][] 67 */ 68 public function get_from_location_provider(): array { 69 return [ 70 ['get_from_instanceid', 'id'], 71 ['get_from_cmid', 'cmid'], 72 ]; 73 } 74 75 /** 76 * Get an instance from a cmid. 77 * @covers ::get_from_cmid 78 */ 79 public function test_get_from_cmid(): void { 80 $this->resetAfterTest(); 81 82 [ 83 'record' => $record, 84 'cm' => $cm, 85 ] = $this->get_test_instance(); 86 87 $instance = instance::get_from_cmid($cm->id); 88 89 $this->assertInstanceOf(instance::class, $instance); 90 $this->assertEquals($record->id, $instance->get_instance_id()); 91 $this->assertEquals($cm->id, $instance->get_cm()->id); 92 } 93 94 /** 95 * If the instance was not found, and exception should be thrown. 96 * @covers ::get_from_cmid 97 */ 98 public function test_get_from_cmid_not_found(): void { 99 $this->assertNull(instance::get_from_cmid(100)); 100 } 101 102 /** 103 * If the instance was not found, and exception should be thrown. 104 * @covers ::get_from_instanceid 105 */ 106 public function test_get_from_instance_not_found(): void { 107 $this->assertNull(instance::get_from_instanceid(100)); 108 } 109 110 /** 111 * Get from meeting id 112 * 113 * @covers ::get_from_meetingid 114 */ 115 public function test_get_from_meetingid(): void { 116 $this->resetAfterTest(); 117 118 [ 119 'record' => $record, 120 ] = $this->get_test_instance(); 121 122 // The meetingid is confusingly made up of a meetingid field, courseid, instanceid, and groupid. 123 $instance = instance::get_from_meetingid(sprintf( 124 "%s-%s-%s", 125 $record->meetingid, 126 $record->course, 127 $record->id 128 )); 129 130 $this->assertInstanceOf(instance::class, $instance); 131 $this->assertEquals($record->id, $instance->get_instance_id()); 132 $this->assertEquals($record->cmid, $instance->get_cm_id()); 133 $this->assertEquals($record->cmid, $instance->get_cm()->id); 134 } 135 136 /** 137 * Get the get_from_meetingid() function where the meetingid includes a groupid. 138 * 139 * @covers ::get_from_meetingid 140 */ 141 public function test_get_from_meetingid_group(): void { 142 $this->resetAfterTest(); 143 144 [ 145 'record' => $record, 146 'course' => $course, 147 'cm' => $cm, 148 ] = $this->get_test_instance(); 149 150 $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 151 152 $instance = instance::get_from_meetingid( 153 sprintf("%s-%s-%s[0]", $record->meetingid, $record->course, $record->id) 154 ); 155 156 $this->assertEquals($cm->instance, $instance->get_instance_id()); 157 $this->assertEquals($cm->id, $instance->get_cm_id()); 158 } 159 160 /** 161 * Ensure that invalid meetingids throw an appropriate exception. 162 * 163 * @dataProvider invalid_meetingid_provider 164 * @param string $meetingid 165 * @covers ::get_from_meetingid 166 */ 167 public function test_get_from_meetingid_invalid(string $meetingid): void { 168 $this->expectException(moodle_exception::class); 169 instance::get_from_meetingid($meetingid); 170 } 171 172 /** 173 * Provide invalid meeting examples 174 * 175 * @return \string[][] 176 */ 177 public function invalid_meetingid_provider(): array { 178 // Meeting IDs are in the formats: 179 // - <meetingid[string]>-<courseid[number]>-<instanceid[number]> 180 // - <meetingid[string]>-<courseid[number]>-<instanceid[number]>[<groupid[number]>] 181 // Note: deducing the group from meeting id will soon be deprecated. 182 return [ 183 'Non-numeric instanceid' => ['aaa-123-aaa'], 184 ]; 185 } 186 187 /** 188 * Test the get_all_instances_in_course function. 189 * 190 * @covers ::get_all_instances_in_course 191 */ 192 public function test_get_all_instances_in_course(): void { 193 $this->resetAfterTest(); 194 195 $course = $this->getDataGenerator()->create_course(); 196 $records = []; 197 for ($i = 0; $i < 5; $i++) { 198 $this->getDataGenerator()->create_module('bigbluebuttonbn', [ 199 'course' => $course->id, 200 ]); 201 } 202 203 $instances = instance::get_all_instances_in_course($course->id); 204 $this->assertCount(5, $instances); 205 foreach ($instances as $instance) { 206 $this->assertInstanceOf(instance::class, $instance); 207 } 208 } 209 210 /** 211 * Get test instance from data 212 * 213 * @param array $data 214 * @return array 215 */ 216 protected function get_test_instance(array $data = []): array { 217 $course = $this->getDataGenerator()->create_course(); 218 $record = $this->getDataGenerator()->create_module('bigbluebuttonbn', array_merge([ 219 'course' => $course->id, 220 ], $data)); 221 $cm = get_fast_modinfo($course)->instances['bigbluebuttonbn'][$record->id]; 222 223 return [ 224 'course' => $course, 225 'record' => $record, 226 'cm' => $cm, 227 ]; 228 } 229 230 /** 231 * Test the get_meeting_id function for a meeting configured for a group. 232 * 233 * @covers ::get_meeting_id 234 */ 235 public function test_get_meeting_id_with_groups(): void { 236 $this->resetAfterTest(); 237 238 [ 239 'record' => $record, 240 'course' => $course, 241 ] = $this->get_test_instance(); 242 243 $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 244 245 $instance = instance::get_from_instanceid($record->id); 246 247 // No group. 248 $this->assertEquals( 249 sprintf("%s-%s-%s[0]", $record->meetingid, $record->course, $record->id), 250 $instance->get_meeting_id(0) 251 ); 252 253 // Specified group. 254 $this->assertEquals( 255 sprintf("%s-%s-%s[%d]", $record->meetingid, $record->course, $record->id, $group->id), 256 $instance->get_meeting_id($group->id) 257 ); 258 } 259 260 /** 261 * Test the get_meeting_id function for a meeting configured for a group. 262 * 263 * @covers ::get_meeting_id 264 */ 265 public function test_get_meeting_id_without_groups(): void { 266 $this->resetAfterTest(); 267 268 [ 269 'record' => $record, 270 'course' => $course, 271 ] = $this->get_test_instance(); 272 273 $instance = instance::get_from_instanceid($record->id); 274 275 // No group. 276 $this->assertEquals( 277 sprintf("%s-%s-%s[0]", $record->meetingid, $record->course, $record->id), 278 $instance->get_meeting_id(null) 279 ); 280 } 281 282 /** 283 * Data provider to check the various room_available scenarios' 284 * 285 * @return array 286 */ 287 public function is_currently_open_provider(): array { 288 return [ 289 'No opening or closing time set: Is open' => [null, null, true], 290 'Opening time set in the past, no closing: Is open' => [-DAYSECS, null, true], 291 'Opening time set in the future, no closing: Is closed' => [+DAYSECS, null, false], 292 'Closing time set in the past, no opening: Is closed' => [null, -DAYSECS, false], 293 'Closing time set in the future, no opening: Is open' => [null, +DAYSECS, true], 294 'Opening and closing in the past: Is closed' => [-WEEKSECS, -DAYSECS, false], 295 'Opening and closing in the future: Is closed' => [+DAYSECS, +WEEKSECS, false], 296 'Opening in the past, Closing in the future: Is open' => [-DAYSECS, +DAYSECS, true], 297 ]; 298 } 299 300 /** 301 * Check instance currently open 302 * 303 * @dataProvider is_currently_open_provider 304 * @param null|int $openingtime 305 * @param null|int $closingtime 306 * @param bool $expected 307 * @covers ::is_currently_open 308 */ 309 public function test_is_currently_open(?int $openingtime, ?int $closingtime, bool $expected): void { 310 $stub = $this->getMockBuilder(instance::class) 311 ->onlyMethods(['get_instance_var']) 312 ->disableOriginalConstructor() 313 ->getMock(); 314 315 if ($openingtime) { 316 $openingtime = $openingtime + time(); 317 } 318 319 if ($closingtime) { 320 $closingtime = $closingtime + time(); 321 } 322 323 $stub->method('get_instance_var') 324 ->willReturnCallback(function($var) use ($openingtime, $closingtime) { 325 if ($var === 'openingtime') { 326 return $openingtime; 327 } 328 329 return $closingtime; 330 }); 331 $this->assertEquals($expected, $stub->is_currently_open()); 332 } 333 334 /** 335 * Ensure that the user_must_wait_to_join function works as expectd. 336 * 337 * @dataProvider user_must_wait_to_join_provider 338 * @param bool $isadmin 339 * @param bool $ismoderator 340 * @param bool $haswaitingroom 341 * @param bool $expected 342 * @covers ::user_must_wait_to_join 343 */ 344 public function test_user_must_wait_to_join(bool $isadmin, bool $ismoderator, bool $haswaitingroom, bool $expected): void { 345 $stub = $this->getMockBuilder(instance::class) 346 ->setMethods([ 347 'get_instance_var', 348 'is_admin', 349 'is_moderator', 350 ]) 351 ->disableOriginalConstructor() 352 ->getMock(); 353 354 $stub->method('is_admin')->willReturn($isadmin); 355 $stub->method('is_moderator')->willReturn($ismoderator); 356 $stub->method('get_instance_var')->willReturn($haswaitingroom); 357 358 $this->assertEquals($expected, $stub->user_must_wait_to_join()); 359 } 360 361 /** 362 * Data provider for the user_must_wait_to_join function. 363 * 364 * @return array 365 */ 366 public function user_must_wait_to_join_provider(): array { 367 return [ 368 'Admins must never wait to join (waiting disabled)' => [true, false, false, false], 369 'Admins must never wait to join (waiting enabled)' => [true, false, true, false], 370 'Moderators must never wait to join (waiting disabled)' => [false, true, false, false], 371 'Moderators must never wait to join (waiting enabled)' => [false, true, true, false], 372 'Other users must wait to join if waiting enabled' => [false, false, true, true], 373 'Other users cannot wait to join if waiting disabled' => [false, false, false, false], 374 ]; 375 } 376 377 /** 378 * Ensure that the does_current_user_count_towards_user_limit function works as expectd. 379 * 380 * @dataProvider does_current_user_count_towards_user_limit_provider 381 * @param bool $isadmin 382 * @param bool $ismoderator 383 * @param bool $expected 384 * @covers ::does_current_user_count_towards_user_limit 385 */ 386 public function test_does_current_user_count_towards_user_limit( 387 bool $isadmin, 388 bool $ismoderator, 389 bool $expected 390 ): void { 391 $stub = $this->getMockBuilder(instance::class) 392 ->setMethods([ 393 'is_admin', 394 'is_moderator', 395 ]) 396 ->disableOriginalConstructor() 397 ->getMock(); 398 399 $stub->method('is_admin')->willReturn($isadmin); 400 $stub->method('is_moderator')->willReturn($ismoderator); 401 402 $this->assertEquals($expected, $stub->does_current_user_count_towards_user_limit()); 403 } 404 405 /** 406 * Data provider for the does_current_user_count_towards_user_limit function. 407 * 408 * @return array 409 */ 410 public function does_current_user_count_towards_user_limit_provider(): array { 411 return [ 412 'Admin does not count' => [true, false, false], 413 'Moderator does not count' => [false, true, false], 414 'Other users do count' => [false, false, true], 415 ]; 416 } 417 418 /** 419 * Ensure that the does_current_user_count_towards_user_limit function works as expectd. 420 * 421 * @dataProvider get_current_user_password_provider 422 * @param bool $isadmin 423 * @param bool $ismoderator 424 * @param bool $expectedmodpassword 425 * @covers ::get_current_user_password 426 */ 427 public function test_get_current_user_password(bool $isadmin, bool $ismoderator, bool $expectedmodpassword): void { 428 $stub = $this->getMockBuilder(instance::class) 429 ->setMethods([ 430 'is_admin', 431 'is_moderator', 432 'get_moderator_password', 433 'get_viewer_password', 434 ]) 435 ->disableOriginalConstructor() 436 ->getMock(); 437 438 $stub->method('is_admin')->willReturn($isadmin); 439 $stub->method('is_moderator')->willReturn($ismoderator); 440 $stub->method('get_moderator_password')->willReturn('Moderator Password'); 441 $stub->method('get_viewer_password')->willReturn('Viewer Password'); 442 443 if ($expectedmodpassword) { 444 $this->assertEquals('Moderator Password', $stub->get_current_user_password()); 445 } else { 446 $this->assertEquals('Viewer Password', $stub->get_current_user_password()); 447 } 448 } 449 450 /** 451 * Data provider for the get_current_user_password function. 452 * 453 * @return array 454 */ 455 public function get_current_user_password_provider(): array { 456 return [ 457 'Admin is a moderator' => [true, false, true], 458 'Moderator is a moderator' => [false, true, true], 459 'Others are a viewer' => [false, false, false], 460 ]; 461 } 462 463 /** 464 * Ensure that the get_current_user_role function works as expected. 465 * 466 * @dataProvider get_current_user_role_provider 467 * @param bool $isadmin 468 * @param bool $ismoderator 469 * @param bool $expectedmodrole 470 * @covers ::get_current_user_role 471 */ 472 public function test_get_current_user_role(bool $isadmin, bool $ismoderator, bool $expectedmodrole): void { 473 $stub = $this->getMockBuilder(instance::class) 474 ->setMethods([ 475 'is_admin', 476 'is_moderator', 477 ]) 478 ->disableOriginalConstructor() 479 ->getMock(); 480 481 $stub->method('is_admin')->willReturn($isadmin); 482 $stub->method('is_moderator')->willReturn($ismoderator); 483 484 if ($expectedmodrole) { 485 $this->assertEquals('MODERATOR', $stub->get_current_user_role()); 486 } else { 487 $this->assertEquals('VIEWER', $stub->get_current_user_role()); 488 } 489 } 490 491 /** 492 * Data provider for the get_current_user_role function. 493 * 494 * @return array 495 */ 496 public function get_current_user_role_provider(): array { 497 return [ 498 'Admin is a moderator' => [true, false, true], 499 'Moderator is a moderator' => [false, true, true], 500 'Others are a viewer' => [false, false, false], 501 ]; 502 } 503 504 /** 505 * Tests for the allow_recording_start_stop function. 506 * 507 * @dataProvider allow_recording_start_stop_provider 508 * @param bool $isrecorded 509 * @param bool $showbuttons 510 * @param bool $expected 511 * @covers ::allow_recording_start_stop 512 */ 513 public function test_allow_recording_start_stop( 514 bool $isrecorded, 515 bool $showbuttons, 516 bool $expected 517 ): void { 518 $stub = $this->getMockBuilder(instance::class) 519 ->setMethods([ 520 'is_recorded', 521 'should_show_recording_button', 522 ]) 523 ->disableOriginalConstructor() 524 ->getMock(); 525 526 $stub->method('is_recorded')->willReturn($isrecorded); 527 $stub->method('should_show_recording_button')->willReturn($showbuttons); 528 529 $this->assertEquals($expected, $stub->allow_recording_start_stop()); 530 } 531 532 /** 533 * Data provider for the allow_recording_start_stop function. 534 * 535 * @return array 536 */ 537 public function allow_recording_start_stop_provider(): array { 538 return [ 539 'Meeting is not recorded: No start/stop' => [false, false, false], 540 'Meeting recorded, Buttons shown: Allow' => [true, true, true], 541 'Meeting recorded, Buttons not shown: Deny' => [true, false, false], 542 ]; 543 } 544 545 546 /** 547 * Test get user id (guest or current user) 548 * @covers \mod_bigbluebuttonbn\instance::get_user_id 549 */ 550 public function test_get_user_id(): void { 551 $this->resetAfterTest(); 552 $this->setUser(null); 553 ['record' => $record ] = $this->get_test_instance(); 554 $instance = instance::get_from_instanceid($record->id); 555 $this->assertEquals(0, $instance->get_user_id()); 556 $user = $this->getDataGenerator()->create_user(); 557 $this->setUser($user); 558 $this->assertEquals($user->id, $instance->get_user_id()); 559 } 560 561 /** 562 * Test guest access URL 563 * 564 * @covers ::get_guest_access_url 565 */ 566 public function test_get_guest_access_url() { 567 global $CFG; 568 $this->resetAfterTest(); 569 ['record' => $record ] = $this->get_test_instance(['guestallowed' => true]); 570 $CFG->bigbluebuttonbn['guestaccess_enabled'] = 1; 571 $instance = instance::get_from_instanceid($record->id); 572 $this->assertNotEmpty($instance->get_guest_access_url()); 573 } 574 575 /** 576 * Test guest allowed flag 577 * 578 * @covers ::is_guest_allowed 579 */ 580 public function test_is_guest_allowed() { 581 global $CFG; 582 $this->resetAfterTest(); 583 ['record' => $record ] = $this->get_test_instance(['guestallowed' => true]); 584 $CFG->bigbluebuttonbn['guestaccess_enabled'] = 1; 585 $instance = instance::get_from_instanceid($record->id); 586 $this->assertTrue($instance->is_guest_allowed()); 587 $CFG->bigbluebuttonbn['guestaccess_enabled'] = 0; 588 $this->assertFalse($instance->is_guest_allowed()); 589 } 590 591 /** 592 * Test private method get_instance_info_retriever 593 * 594 * @covers ::get_instance_info_retriever 595 */ 596 public function test_get_instance_info_retriever() { 597 $this->resetAfterTest(); 598 [ 599 'record' => $record, 600 'cm' => $cm, 601 ] = $this->get_test_instance(); 602 $instance = instance::get_from_instanceid($record->id); 603 $instancereflection = new \ReflectionClass($instance); 604 $getinstanceinforetriever = $instancereflection->getMethod('get_instance_info_retriever'); 605 $getinstanceinforetriever->setAccessible(true); 606 $this->assertInstanceOf('\mod_bigbluebuttonbn\instance', 607 $getinstanceinforetriever->invoke($instance, $record->id, instance::IDTYPE_INSTANCEID)); 608 $this->assertEquals($cm->id, $instance->get_cm_id()); 609 } 610 611 /** 612 * Test guest access password 613 * 614 * @covers ::get_guest_access_password 615 */ 616 public function get_guest_access_password() { 617 global $CFG; 618 $this->resetAfterTest(); 619 ['record' => $record ] = $this->get_test_instance(['guestallowed' => true]); 620 $CFG->bigbluebuttonbn['guestaccess_enabled'] = 1; 621 $instance = instance::get_from_instanceid($record->id); 622 $this->assertNotEmpty($instance->get_guest_access_password()); 623 } 624 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body