Rev 1 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Meeting test.** @package mod_bigbluebuttonbn* @copyright 2018 - present, Blindside Networks Inc* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later* @author Jesus Federico (jesus [at] blindsidenetworks [dt] com)*/namespace mod_bigbluebuttonbn;use mod_bigbluebuttonbn\test\testcase_helper_trait;/*** Meeting tests class.** @package mod_bigbluebuttonbn* @copyright 2018 - present, Blindside Networks Inc* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later* @author Jesus Federico (jesus [at] blindsidenetworks [dt] com)* @covers \mod_bigbluebuttonbn\meeting* @coversDefaultClass \mod_bigbluebuttonbn\meeting*/class meeting_test extends \advanced_testcase {use testcase_helper_trait;/*** Setup Test*/public function setUp(): void {parent::setUp();$this->initialise_mock_server();// We do not force the group mode so we can change the activity group mode during test.$this->course = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS]);$this->getDataGenerator()->create_group(['name' => 'G1', 'courseid' => $this->course->id]);$this->getDataGenerator()->create_group(['name' => 'G2', 'courseid' => $this->course->id]);}/*** Get a list of possible test (dataprovider)** @return array[]*/public function get_instance_types_meeting_info(): array {return ['Instance Type ALL - No Group' => ['type' => instance::TYPE_ALL,'groupname' => null,'groupmode' => NOGROUPS,'canjoin' => ['useringroup' => true, 'usernotingroup' => true],],'Instance Type ALL - Group 1 - Visible groups' => ['type' => instance::TYPE_ALL,'groupname' => 'G1','groupmode' => VISIBLEGROUPS,'canjoin' => ['useringroup' => true, 'usernotingroup' => true],],'Instance Type ALL - Group 1 - Separate groups' => ['type' => instance::TYPE_ALL,'groupname' => 'G1','groupmode' => SEPARATEGROUPS,'canjoin' => ['useringroup' => true, 'usernotingroup' => false],],'Instance Type ROOM Only - No Group' => ['type' => instance::TYPE_ROOM_ONLY,'groupname' => null,'groupmode' => NOGROUPS,'canjoin' => ['useringroup' => true, 'usernotingroup' => true],],'Instance Type ROOM Only - Group 1 - Visible groups' => ['type' => instance::TYPE_ROOM_ONLY,'groupname' => 'G1','groupmode' => VISIBLEGROUPS,'canjoin' => ['useringroup' => true, 'usernotingroup' => true],],'Instance Type ROOM Only - Group 1 - Separate groups' => ['type' => instance::TYPE_ROOM_ONLY,'groupname' => 'G1','groupmode' => SEPARATEGROUPS,'canjoin' => ['useringroup' => true, 'usernotingroup' => false],],'Instance Type Recording Only - No Group' => ['type' => instance::TYPE_RECORDING_ONLY,'groupname' => null,'groupmode' => NOGROUPS,'canjoin' => ['useringroup' => false, 'usernotingroup' => false]],'Instance Type Recording Only - Group 1' => ['type' => instance::TYPE_RECORDING_ONLY,'groupname' => 'G1','groupmode' => VISIBLEGROUPS,'canjoin' => ['useringroup' => false, 'usernotingroup' => false]]];}/*** Test that create meeing is working for all types.** @dataProvider get_instance_types_meeting_info* @param int $type* @param string|null $groupname* @covers ::create_meeting* @covers ::create_meeting_data* @covers ::create_meeting_metadata*/public function test_create_meeting(int $type, ?string $groupname): void {$this->resetAfterTest();[$meeting, $useringroup, $usernotingroup, $groupid, $activity] =$this->prepare_meeting($type, $groupname, SEPARATEGROUPS, false);$meeting->create_meeting();$meetinginfo = $meeting->get_meeting_info();$this->assertNotNull($meetinginfo);$this->assertEquals($activity->id, $meetinginfo->bigbluebuttonbnid);$this->assertFalse($meetinginfo->statusrunning);$this->assertStringContainsString("is ready", $meetinginfo->statusmessage);$this->assertEquals($groupid, $meetinginfo->groupid);}/*** Test for get meeting info for all types** @param int $type* @param string|null $groupname* @dataProvider get_instance_types_meeting_info* @covers ::get_meeting_info* @covers ::do_get_meeting_info*/public function test_get_meeting_info(int $type, ?string $groupname): void {$this->resetAfterTest();[$meeting, $useringroup, $usernotingroup, $groupid, $activity] = $this->prepare_meeting($type, $groupname);$meetinginfo = $meeting->get_meeting_info();$this->assertNotNull($meetinginfo);$this->assertEquals($activity->id, $meetinginfo->bigbluebuttonbnid);$this->assertTrue($meetinginfo->statusrunning);$this->assertStringContainsString("in progress", $meetinginfo->statusmessage);$this->assertEquals($groupid, $meetinginfo->groupid);$meeting->end_meeting();$meeting->update_cache();$meetinginfo = $meeting->get_meeting_info();$this->assertFalse($meetinginfo->statusrunning);if ($type == instance::TYPE_ALL) {$this->assertTrue($meetinginfo->features['showroom']);$this->assertTrue($meetinginfo->features['showrecordings']);} else if ($type == instance::TYPE_ROOM_ONLY) {$this->assertTrue($meetinginfo->features['showroom']);$this->assertFalse($meetinginfo->features['showrecordings']);} else if ($type == instance::TYPE_RECORDING_ONLY) {$this->assertFalse($meetinginfo->features['showroom']);$this->assertTrue($meetinginfo->features['showrecordings']);}}/*** Test can join is working for all types** @param int $type* @param string|null $groupname* @param int $groupmode* @param array $canjoin* @dataProvider get_instance_types_meeting_info* @covers ::can_join*/public function test_can_join(int $type, ?string $groupname, int $groupmode, array $canjoin): void {$this->resetAfterTest();[$meeting, $useringroup, $usernotingroup, $groupid, $activity] = $this->prepare_meeting($type, $groupname, $groupmode);$this->setUser($useringroup);$meeting->update_cache();$this->assertEquals($canjoin['useringroup'], $meeting->can_join());if ($meeting->can_join()) {$meetinginfo = $meeting->get_meeting_info();$this->assertStringContainsString("The session is in progress.", $meetinginfo->statusmessage);}if ($groupname) {$this->setUser($usernotingroup);$meeting->update_cache();$this->assertEquals($canjoin['usernotingroup'], $meeting->can_join());}}/*** Test can join is working if opening/closing time are set** @param int $type* @param string|null $groupname* @param int $groupmode* @param array $canjoin* @param array $dates* @dataProvider get_data_can_join_with_dates* @covers ::can_join*/public function test_can_join_with_dates(int $type, ?string $groupname, int $groupmode, array $canjoin, array $dates): void {// Apply the data provider relative values to now.array_walk($dates, function(&$val) {$val = time() + $val;});$this->resetAfterTest();[$meeting, $useringroup, $usernotingroup, $groupid, $activity] =$this->prepare_meeting($type, $groupname, $groupmode, true, $dates);$this->setUser($useringroup);$meeting->update_cache();$this->assertEquals($canjoin['useringroup'], $meeting->can_join());// We check that admin can not join outside opening/closing times either.$this->setAdminUser();$this->assertEquals(false, $meeting->can_join());if ($groupname) {$this->setUser($usernotingroup);$meeting->update_cache();$this->assertEquals($canjoin['usernotingroup'], $meeting->can_join());$this->setAdminUser();$this->assertEquals(false, $meeting->can_join());}}/*** Test can join is working if the "Wait for moderator to join" setting is set and a moderator has not yet joined.** @covers ::join* @covers ::join_meeting*/public function test_join_wait_for_moderator_not_joined(): void {$this->resetAfterTest();$this->setAdminUser();$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');$student = $this->getDataGenerator()->create_and_enrol($this->get_course());$meetinginfo = ['course' => $this->get_course()->id,'type' => instance::TYPE_ALL,'wait' => 1,];$activity = $bbbgenerator->create_instance($meetinginfo, ['wait' => 1,]);$instance = instance::get_from_instanceid($activity->id);$meeting = new meeting($instance);// The moderator has not joined.$this->setUser($student);$meeting->update_cache();$this->expectException(\mod_bigbluebuttonbn\local\exceptions\meeting_join_exception::class);meeting::join_meeting($instance);}/*** Test can join is working if the "Wait for moderator to join" setting is set and a moderator has already joined.** @covers ::join* @covers ::join_meeting*/public function test_join_wait_for_moderator_is_joined(): void {$this->resetAfterTest();$this->setAdminUser();$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');$moderator = $this->getDataGenerator()->create_and_enrol($this->get_course(), 'editingteacher');$student = $this->getDataGenerator()->create_and_enrol($this->get_course());$meetinginfo = ['course' => $this->get_course()->id,'type' => instance::TYPE_ALL,'wait' => 1,'moderators' => 'role:editingteacher',];$activity = $bbbgenerator->create_instance($meetinginfo, ['wait' => 1,]);$instance = instance::get_from_instanceid($activity->id);$meeting = new meeting($instance);$bbbgenerator->create_meeting(['instanceid' => $instance->get_instance_id(),]);$this->setUser($moderator);$meeting->update_cache();$joinurl = $meeting->join(logger::ORIGIN_BASE);$this->assertIsString($joinurl);$this->join_meeting($joinurl);$meeting->update_cache();$this->assertCount(1, $meeting->get_attendees());// The student can now join the meeting as a moderator is present.$this->setUser($student);$joinurl = $meeting->join(logger::ORIGIN_BASE);$this->assertIsString($joinurl);}/*** Test can join is working if the "user limit" setting is set and reached.** @covers ::join* @covers ::join_meeting*/public function test_join_user_limit_reached(): void {$this->resetAfterTest();set_config('bigbluebuttonbn_userlimit_editable', true);$this->setAdminUser();$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');$moderator = $this->getDataGenerator()->create_and_enrol($this->get_course(), 'editingteacher');$student1 = $this->getDataGenerator()->create_and_enrol($this->get_course());$student2 = $this->getDataGenerator()->create_and_enrol($this->get_course());$meetinginfo = ['course' => $this->get_course()->id,'type' => instance::TYPE_ALL,'userlimit' => 2,];$activity = $bbbgenerator->create_instance($meetinginfo, ['userlimit' => 2,]);$instance = instance::get_from_instanceid($activity->id);$meeting = new meeting($instance);$bbbgenerator->create_meeting(['instanceid' => $instance->get_instance_id(),]);// Moderator joins the meeting.$this->setUser($moderator);$this->join_meeting($meeting->join(logger::ORIGIN_BASE));$meeting->update_cache();$this->assertEquals(1, $meeting->get_participant_count());// Student1 joins the meeting.$this->setUser($student1);$this->join_meeting($meeting->join(logger::ORIGIN_BASE));$meeting->update_cache();$this->assertEquals(2, $meeting->get_participant_count());$this->assertTrue($instance->has_user_limit_been_reached($meeting->get_participant_count()));// Student2 tries to join but the limit has been reached.$this->setUser($student2);$meeting->update_cache();$this->assertFalse($meeting->can_join());$this->expectException(\mod_bigbluebuttonbn\local\exceptions\meeting_join_exception::class);meeting::join_meeting($instance);}/*** Test that attendees returns the right list of attendees** @covers ::get_attendees*/public function test_get_attendees(): void {$this->resetAfterTest();[$meeting, $useringroup, $usernotingroup, $groupid, $activity] =$this->prepare_meeting(instance::TYPE_ALL, null, NOGROUPS, true);$this->setUser($useringroup);$this->join_meeting($meeting->join(logger::ORIGIN_BASE));$meeting->update_cache();$this->assertCount(1, $meeting->get_attendees());$otheruser = $this->getDataGenerator()->create_and_enrol($this->get_course());$this->setUser($otheruser);$meeting->update_cache();$this->join_meeting($meeting->join(logger::ORIGIN_BASE));$meeting->update_cache();$this->assertCount(2, $meeting->get_attendees());}/*** Test that attendees returns the right list of attendees** @covers ::get_attendees*/public function test_participant_count(): void {$this->resetAfterTest();[$meeting, $useringroup, $usernotingroup, $groupid, $activity] =$this->prepare_meeting(instance::TYPE_ALL, null, NOGROUPS, true);$this->setUser($useringroup);$this->join_meeting($meeting->join(logger::ORIGIN_BASE));$meeting->update_cache();$meetinginfo = $meeting->get_meeting_info();$this->assertEquals(1, $meetinginfo->participantcount);$this->assertEquals(1, $meetinginfo->totalusercount);$this->assertEquals(0, $meetinginfo->moderatorcount);$this->setUser($usernotingroup);$this->join_meeting($meeting->join(logger::ORIGIN_BASE));$meeting->update_cache();$meetinginfo = $meeting->get_meeting_info();$this->assertEquals(2, $meetinginfo->participantcount);$this->assertEquals(2, $meetinginfo->totalusercount);$this->assertEquals(0, $meetinginfo->moderatorcount);$this->setAdminUser();$this->join_meeting($meeting->join(logger::ORIGIN_BASE));$meeting->update_cache();$meetinginfo = $meeting->get_meeting_info();$this->assertEquals(2, $meetinginfo->participantcount);$this->assertEquals(3, $meetinginfo->totalusercount);$this->assertEquals(1, $meetinginfo->moderatorcount);}/*** Send a join meeting API CALL** @param string $url*/protected function join_meeting(string $url) {$curl = new \curl();$url = new \moodle_url($url);$curl->get($url->out_omit_querystring(), $url->params());}/*** Get a list of possible test (dataprovider)** @return array[]*/public function get_data_can_join_with_dates(): array {return ['Instance Type ALL - No Group - Closed in past' => ['type' => instance::TYPE_ALL,'groupname' => null,'groupmode' => NOGROUPS,'canjoin' => ['useringroup' => false, 'usernotingroup' => false],'dates' => ['openingtime' => -7200, 'closingtime' => -3600]],'Instance Type ALL - No Group - Open in future' => ['type' => instance::TYPE_ALL,'groupname' => null,'groupmode' => NOGROUPS,'canjoin' => ['useringroup' => false, 'usernotingroup' => false],'dates' => ['openingtime' => 3600, 'closingtime' => 7200]],];}/*** Helper to prepare for a meeting** @param int $type* @param string|null $groupname* @param int $groupmode* @param bool $createmeeting* @param array $dates* @return array*/protected function prepare_meeting(int $type, ?string $groupname, int $groupmode = SEPARATEGROUPS, bool $createmeeting = true,array $dates = []) {$this->setAdminUser();$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');$groupid = 0;$useringroup = $this->getDataGenerator()->create_and_enrol($this->get_course());$usernotingroup = $this->getDataGenerator()->create_and_enrol($this->get_course());if (!empty($groupname)) {$groupid = groups_get_group_by_name($this->get_course()->id, $groupname);$this->getDataGenerator()->create_group_member(['groupid' => $groupid, 'userid' => $useringroup->id]);}$meetinginfo = ['course' => $this->get_course()->id,'type' => $type];if ($dates) {$meetinginfo = array_merge($meetinginfo, $dates);};$activity = $bbbgenerator->create_instance($meetinginfo, ['groupmode' => $groupmode]);$instance = instance::get_from_instanceid($activity->id);if ($groupid) {$instance->set_group_id($groupid);}if ($createmeeting) {// Create the meetings on the mock server, so we can join it as a simple user.$bbbgenerator->create_meeting(['instanceid' => $instance->get_instance_id(),'groupid' => $instance->get_group_id()]);}$meeting = new meeting($instance);return [$meeting, $useringroup, $usernotingroup, $groupid, $activity];}}