first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+124
View File
@@ -0,0 +1,124 @@
<?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/>.
namespace mod_bigbluebuttonbn\external;
use core_external\external_api;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\test\testcase_helper_trait;
use moodle_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Tests for the update_course class.
*
* @package mod_bigbluebuttonbn
* @category test
* @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \mod_bigbluebuttonbn\external\can_join
*/
class can_join_test extends \externallib_advanced_testcase {
use testcase_helper_trait;
/**
* Setup for test
*/
public function setUp(): void {
parent::setUp();
$this->initialise_mock_server();
}
/**
* Helper
*
* @param mixed ...$params
* @return mixed
*/
protected function can_join(...$params) {
$canjoin = can_join::execute(...$params);
return external_api::clean_returnvalue(can_join::execute_returns(), $canjoin);
}
/**
* Test execute API CALL with no instance
*/
public function test_execute_no_instance(): void {
$this->resetAfterTest();
$canjoin = $this->can_join(1234, 5678);
$this->assertIsArray($canjoin);
$this->assertArrayHasKey('can_join', $canjoin);
$this->assertEquals(false, $canjoin['can_join']);
}
/**
* Test execute API CALL without login
*/
public function test_execute_without_login(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = $this->getDataGenerator()->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$this->expectException(moodle_exception::class);
$this->can_join($instance->get_cm_id());
}
/**
* Test execute API CALL with invalid login
*/
public function test_execute_with_invalid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_user();
$this->setUser($user);
$this->expectException(moodle_exception::class);
$this->can_join($instance->get_cm_id());
}
/**
* When login as a student
*/
public function test_execute_with_valid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'student');
$this->setUser($user);
$canjoin = $this->can_join($instance->get_cm_id());
$this->assertIsArray($canjoin);
$this->assertArrayHasKey('can_join', $canjoin);
$this->assertEquals(true, $canjoin['can_join']);
}
}
@@ -0,0 +1,155 @@
<?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/>.
namespace mod_bigbluebuttonbn\external;
use core_external\external_api;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\test\testcase_helper_trait;
use require_login_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Tests for the completion_validate class.
*
* @package mod_bigbluebuttonbn
* @category test
* @copyright 2021 - present, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent@call-learning.fr)
* @covers \mod_bigbluebuttonbn\external\completion_validate
*/
class completion_validate_test extends \externallib_advanced_testcase {
use testcase_helper_trait;
/**
* Setup for test
*/
public function setUp(): void {
parent::setUp();
$this->initialise_mock_server();
}
/**
* Helper
*
* @param mixed ...$params
* @return mixed
*/
protected function completion_validate(...$params) {
$returnvalue = completion_validate::execute(...$params);
return external_api::clean_returnvalue(completion_validate::execute_returns(), $returnvalue);
}
/**
* Test execute API CALL with no instance
*/
public function test_execute_no_instance(): void {
$this->resetAfterTest();
$result = $this->completion_validate(1234);
$this->assertIsArray($result);
$this->assertArrayHasKey('warnings', $result);
$this->assertEquals([
'item' => 'mod_bigbluebuttonbn',
'itemid' => 1234,
'warningcode' => 'indexerrorbbtn',
'message' => 'BigBlueButton ID 1234 is incorrect',
], $result['warnings'][0]);
}
/**
* Test execute API CALL without login
*/
public function test_execute_without_login(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = $this->getDataGenerator()->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$this->expectException(require_login_exception::class);
$this->completion_validate($instance->get_instance_id());
}
/**
* Test execute API CALL with invalid login
*/
public function test_execute_with_invalid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_user($course);
$this->setUser($user);
$this->expectException(require_login_exception::class);
$this->completion_validate($instance->get_instance_id());
}
/**
* When login as a student
*/
public function test_execute_with_valid_login_but_student(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'student');
$this->setUser($user);
$returnvalue = $this->completion_validate($instance->get_instance_id());
$this->assertArrayHasKey('warnings', $returnvalue);
$this->assertEquals([
'item' => 'mod_bigbluebuttonbn',
'itemid' => $record->id,
'warningcode' => 'nopermissions',
'message' => 'Sorry, but you do not currently have permissions to do that (completion_validate).',
], $returnvalue['warnings'][0]);
}
/**
* When login as a student
*/
public function test_execute_with_valid_login_with_teacher(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'editingteacher');
$this->setUser($user);
$returnvalue = $this->completion_validate($instance->get_instance_id());
$this->assertArrayHasKey('warnings', $returnvalue);
$this->assertEmpty($returnvalue['warnings']);
}
}
+172
View File
@@ -0,0 +1,172 @@
<?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/>.
namespace mod_bigbluebuttonbn\external;
use core_external\external_api;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\meeting;
use mod_bigbluebuttonbn\test\testcase_helper_trait;
use moodle_exception;
use require_login_exception;
use core_external\restricted_context_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Tests for the update_course class.
*
* @package mod_bigbluebuttonbn
* @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \mod_bigbluebuttonbn\external\end_meeting
*/
class end_meeting_test extends \externallib_advanced_testcase {
use testcase_helper_trait;
/**
* Setup for test
*/
public function setUp(): void {
parent::setUp();
$this->initialise_mock_server();
}
/**
* Helper
*
* @param mixed ...$params
* @return array|bool|mixed
*/
protected function end_meeting(...$params) {
$returnvalue = end_meeting::execute(...$params);
return external_api::clean_returnvalue(end_meeting::execute_returns(), $returnvalue);
}
/**
* Test execute API CALL with no instance
*/
public function test_execute_no_instance(): void {
$this->resetAfterTest();
$this->expectException(moodle_exception::class);
$endmeeting = $this->end_meeting(1234, 5678);
}
/**
* Test execute API CALL without login
*/
public function test_execute_without_login(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = $this->getDataGenerator()->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$this->expectException(require_login_exception::class);
$this->end_meeting($instance->get_instance_id(), 0);
}
/**
* Test execute API CALL with invalid login
*/
public function test_execute_with_invalid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_user();
$this->setUser($user);
$this->expectException(require_login_exception::class);
$this->end_meeting($instance->get_instance_id(), 0);
}
/**
* When login as a student
*/
public function test_execute_with_student_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'student');
$this->setUser($user);
$this->expectException(restricted_context_exception::class);
$this->end_meeting($instance->get_instance_id(), 0);
}
/**
* Test execute admin logic
*/
public function test_execute_with_admin_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$plugingenerator = $generator->get_plugin_generator('mod_bigbluebuttonbn');
$plugingenerator->create_meeting([
'instanceid' => $instance->get_instance_id(),
]);
$this->setAdminUser();
$result = $this->end_meeting($instance->get_instance_id(), 0);
$this->assertIsArray($result);
// TODO Check that the meeting was ended on the remote.
}
/**
* Test execute admin logic
*/
public function test_execute_end_meeting_already_ended(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$plugingenerator = $generator->get_plugin_generator('mod_bigbluebuttonbn');
$plugingenerator->create_meeting([
'instanceid' => $instance->get_instance_id(),
]);
// Then end the meeting.
// Execute the end command.
$meeting = new meeting($instance);
$meeting->end_meeting();
$this->setAdminUser();
$result = $this->end_meeting($instance->get_instance_id(), 0);
$this->assertIsArray($result);
// TODO Check that the meeting was ended on the remote.
}
}
@@ -0,0 +1,180 @@
<?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/>.
namespace mod_bigbluebuttonbn\external;
use core_external\external_api;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\test\testcase_helper_trait;
use moodle_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Tests for the get_bigbluebuttons_by_courses class.
*
* @package mod_bigbluebuttonbn
* @category test
* @copyright 2021 - present, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent@call-learning.fr)
* @covers \mod_bigbluebuttonbn\external\get_bigbluebuttonbns_by_courses
*/
class get_bigbluebuttons_by_courses_test extends \externallib_advanced_testcase {
use testcase_helper_trait;
/**
* Setup for test
*/
public function setUp(): void {
parent::setUp();
$this->initialise_mock_server();
}
/**
* Helper
*
* @param mixed ...$params
* @return mixed
*/
protected function get_bigbluebuttons_by_courses(...$params) {
$returnvalue = get_bigbluebuttonbns_by_courses::execute(...$params);
return external_api::clean_returnvalue(get_bigbluebuttonbns_by_courses::execute_returns(), $returnvalue);
}
/**
* Test execute API CALL with no instance
*/
public function test_execute_no_instance(): void {
$this->resetAfterTest();
$bbbactivities = $this->get_bigbluebuttons_by_courses([1234, 5678]);
$this->assertIsArray($bbbactivities);
$this->assertArrayHasKey('bigbluebuttonbns', $bbbactivities);
$this->assertArrayHasKey('warnings', $bbbactivities);
$this->assertEmpty($bbbactivities['bigbluebuttonbns']);
}
/**
* Test execute API CALL without login
*/
public function test_execute_without_login(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = $this->getDataGenerator()->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$this->expectException(moodle_exception::class);
$this->get_bigbluebuttons_by_courses($instance->get_cm_id());
}
/**
* Test execute API CALL with invalid login
*/
public function test_execute_with_invalid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_user();
$this->setUser($user);
$this->expectException(moodle_exception::class);
$this->get_bigbluebuttons_by_courses($instance->get_cm_id());
}
/**
* Test get bbbactivities
*/
public function test_execute_with_valid_login(): void {
$this->resetAfterTest(true);
$generator = $this->getDataGenerator();
// Create a user.
$user = $generator->create_user();
// Create courses to add the modules.
$course1 = $generator->create_course();
$course2 = $generator->create_course();
$bbbs = [];
// First bbb activity.
$bbbs[] = $generator->create_module('bigbluebuttonbn', ['course' => $course1->id]);
// Second bbb activity.
$bbbs[] = $generator->create_module('bigbluebuttonbn', ['course' => $course2->id]);
$generator->enrol_user($user->id, $course1->id, null, 'manual');
$generator->enrol_user($user->id, $course2->id, null, 'manual');
// Set to the user.
self::setUser($user);
// Call the external function passing course ids.
$bbbactivities = $this->get_bigbluebuttons_by_courses([$course1->id, $course2->id]);
$this->assert_same_bbb_activities($bbbs, $bbbactivities['bigbluebuttonbns']);
// Call the external function without passing course id.
$bbbactivities = $this->get_bigbluebuttons_by_courses();
$this->assert_same_bbb_activities($bbbs, $bbbactivities['bigbluebuttonbns']);
// Unenrol user from second course and alter expected bbb activity.
$enrol = enrol_get_plugin('manual');
$enrolinstances = enrol_get_instances($course2->id, true);
foreach ($enrolinstances as $courseenrolinstance) {
if ($courseenrolinstance->enrol == "manual") {
$instance2 = $courseenrolinstance;
break;
}
}
$enrol->unenrol_user($instance2, $user->id);
// Call the external function without passing course id.
$bbbactivities = $this->get_bigbluebuttons_by_courses();
$this->assertCount(1, $bbbactivities['bigbluebuttonbns']);
$this->assertEquals($bbbs[0]->id, $bbbactivities['bigbluebuttonbns'][0]['id']);
// Call for the second course we unenrolled the user from.
$bbbactivities = $this->get_bigbluebuttons_by_courses([$course2->id]);
$this->assertCount(0, $bbbactivities['bigbluebuttonbns']);
}
/**
* Check if the two arrays containing the activities are the same.
*
* @param mixed $expected
* @param mixed $actual
*/
protected function assert_same_bbb_activities($expected, $actual) {
$this->assertCount(count($expected), $actual);
$getids = function($bbb) {
return is_array($bbb) ? $bbb['id'] : $bbb->id;
};
$expectedids = array_map($getids, $expected);
$actualid = array_map($getids, $actual);
sort($expectedids);
sort($actualid);
$this->assertEquals($expectedids, $actualid);
}
}
+259
View File
@@ -0,0 +1,259 @@
<?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/>.
namespace mod_bigbluebuttonbn\external;
use context_course;
use core_external\external_api;
use core_external\restricted_context_exception;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\test\testcase_helper_trait;
use moodle_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Tests for the get_join_url class.
*
* @package mod_bigbluebuttonbn
* @category test
* @copyright 2021 - present, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent@call-learning.fr)
* @covers \mod_bigbluebuttonbn\external\get_join_url
*/
class get_join_url_test extends \externallib_advanced_testcase {
use testcase_helper_trait;
/**
* Setup for test
*/
public function setUp(): void {
parent::setUp();
$this->initialise_mock_server();
}
/**
* Helper
*
* @param mixed ...$params
* @return mixed
*/
protected function get_join_url(...$params) {
$getjoinurl = get_join_url::execute(...$params);
return external_api::clean_returnvalue(get_join_url::execute_returns(), $getjoinurl);
}
/**
* Test execute API CALL with no instance
*/
public function test_execute_no_instance(): void {
$this->resetAfterTest();
$this->expectExceptionMessageMatches('/No such instance.*/');
$joinurl = $this->get_join_url(1234, 5678);
$this->assertIsArray($joinurl);
$this->assertArrayNotHasKey('join_url', $joinurl);
$this->assertEquals(false, $joinurl['join_url']);
}
/**
* Test execute API CALL without login
*/
public function test_execute_without_login(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = $this->getDataGenerator()->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$this->expectException(moodle_exception::class);
$this->get_join_url($instance->get_cm_id());
}
/**
* Test execution with a user who doesn't have the capability to join the meeting
*/
public function test_execute_without_capability(): void {
global $DB;
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = $this->getDataGenerator()->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $this->getDataGenerator()->create_and_enrol($course);
$this->setUser($user);
$student = $DB->get_field('role', 'id', ['shortname' => 'student'], MUST_EXIST);
assign_capability('mod/bigbluebuttonbn:join', CAP_PROHIBIT, $student, context_course::instance($course->id), true);
$this->expectException(restricted_context_exception::class);
$this->get_join_url($instance->get_cm_id());
}
/**
* Test execute API CALL with invalid login
*/
public function test_execute_with_invalid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_user();
$this->setUser($user);
$this->expectException(moodle_exception::class);
$this->get_join_url($instance->get_cm_id());
}
/**
* When login as a student
*/
public function test_execute_with_valid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'student');
$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
// Make sure the meeting is running (this is not the default with the mock server).
$bbbgenerator->create_meeting([
'instanceid' => $instance->get_instance_id(),
'groupid' => $instance->get_group_id()
]);
$this->setUser($user);
$joinurl = $this->get_join_url($instance->get_cm_id());
$this->assertIsArray($joinurl);
$this->assertArrayHasKey('join_url', $joinurl);
$this->assertEmpty($joinurl['warnings']);
$this->assertNotNull($joinurl['join_url']);
}
/**
* Check that URL are different depending on the group.
*/
public function test_execute_with_group(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$g1 = $generator->create_group(['courseid' => $course->id]);
$g2 = $generator->create_group(['courseid' => $course->id]);
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'student');
$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
// Make sure the meeting is running (this is not the default with the mock server).
$bbbgenerator->create_meeting([
'instanceid' => $instance->get_instance_id(),
'groupid' => $instance->get_group_id()
]);
$this->setUser($user);
$joinurlnogroup = $this->get_join_url($instance->get_cm_id());
$joinurlnogroupv2 = $this->get_join_url($instance->get_cm_id());
$joinurlg1 = $this->get_join_url($instance->get_cm_id(), $g1->id);
$joinurlg2 = $this->get_join_url($instance->get_cm_id(), $g2->id);
foreach ([$joinurlnogroup, $joinurlnogroupv2, $joinurlg1, $joinurlg2] as $join) {
$this->assertIsArray($join);
$this->assertArrayHasKey('join_url', $join);
$this->assertEmpty($join['warnings']);
$this->assertNotNull($join['join_url']);
}
$this->assertNotEquals($joinurlnogroup['join_url'], $joinurlg1['join_url']);
$this->assertNotEquals($joinurlg2['join_url'], $joinurlg1['join_url']);
}
/**
* Check that we return the same URL once meeting is started.
*/
public function test_execute_with_same_url(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'student');
$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
// Make sure the meeting is running (this is not the default with the mock server).
$bbbgenerator->create_meeting([
'instanceid' => $instance->get_instance_id(),
'groupid' => $instance->get_group_id()
]);
$this->setUser($user);
$joinurl = $this->get_join_url($instance->get_cm_id());
$joinurlv2 = $this->get_join_url($instance->get_cm_id());
foreach ([$joinurl, $joinurlv2] as $join) {
$this->assertIsArray($join);
$this->assertArrayHasKey('join_url', $join);
$this->assertEmpty($join['warnings']);
$this->assertNotNull($join['join_url']);
}
$this->assertEquals($joinurl['join_url'], $joinurlv2['join_url']);
}
/**
* Check that we return the same URL once meeting is started.
*/
public function test_user_limit(): void {
$this->resetAfterTest();
set_config('bigbluebuttonbn_userlimit_editable', true);
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id, 'userlimit' => 2]);
$user1 = $generator->create_and_enrol($course, 'student');
$user2 = $generator->create_and_enrol($course, 'student');
$instance = instance::get_from_instanceid($record->id);
$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
// Make sure the meeting is running (this is not the default with the mock server).
$bbbgenerator->create_meeting([
'instanceid' => $instance->get_instance_id(),
'groupid' => $instance->get_group_id(),
'participants' => 2
]);
$this->setUser($user1);
$joinurl = $this->get_join_url($instance->get_cm_id());
$this->assertNotNull($joinurl['warnings']);
$this->assertEquals('userlimitreached', $joinurl['warnings'][0]['warningcode']);
}
}
@@ -0,0 +1,472 @@
<?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/>.
namespace mod_bigbluebuttonbn\external;
use core_external\external_api;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\test\testcase_helper_trait;
use require_login_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Tests for the update_course class.
*
* @package mod_bigbluebuttonbn
* @category test
* @copyright 2021 - present, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent@call-learning.fr)
* @covers \mod_bigbluebuttonbn\external\get_recordings
*/
class get_recordings_test extends \externallib_advanced_testcase {
use testcase_helper_trait;
/**
* Setup for test
*/
public function setUp(): void {
parent::setUp();
$this->initialise_mock_server();
}
/**
* Helper
*
* @param mixed ...$params
* @return array|bool|mixed
*/
protected function get_recordings(...$params) {
$recordings = get_recordings::execute(...$params);
return external_api::clean_returnvalue(get_recordings::execute_returns(), $recordings);
}
/**
* Test execute API CALL with no instance
*/
public function test_execute_wrong_instance(): void {
$this->resetAfterTest();
$getrecordings = $this->get_recordings(1234);
$this->assertIsArray($getrecordings);
$this->assertArrayHasKey('status', $getrecordings);
$this->assertEquals(false, $getrecordings['status']);
$this->assertStringContainsString('nosuchinstance', $getrecordings['warnings'][0]['warningcode']);
}
/**
* Test execute API CALL without login
*/
public function test_execute_without_login(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = $this->getDataGenerator()->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$this->expectException(require_login_exception::class);
$this->get_recordings($instance->get_instance_id());
}
/**
* Test execute API CALL with invalid login
*/
public function test_execute_with_invalid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_user();
$this->setUser($user);
$this->expectException(require_login_exception::class);
$this->get_recordings($instance->get_instance_id());
}
/**
* When login as a student
*/
public function test_execute_with_valid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'student');
$this->setUser($user);
$getrecordings = $this->get_recordings($instance->get_instance_id());
$this->assertIsArray($getrecordings);
$this->assertArrayHasKey('status', $getrecordings);
$this->assertEquals(true, $getrecordings['status']);
$this->assertNotEmpty($getrecordings['tabledata']);
$this->assertEquals('[]', $getrecordings['tabledata']['data']);
}
/**
* Check if tools are present for teacher/moderator
*/
public function test_get_recordings_tools(): void {
$this->resetAfterTest();
$dataset = [
'type' => instance::TYPE_ALL,
'groups' => null,
'users' => [['username' => 't1', 'role' => 'editingteacher'], ['username' => 's1', 'role' => 'student']],
'recordingsdata' => [
[['name' => 'Recording1']],
[['name' => 'Recording2']]
],
];
$activityid = $this->create_from_dataset($dataset);
$instance = instance::get_from_instanceid($activityid);
$context = \context_course::instance($instance->get_course_id());
foreach ($dataset['users'] as $userdef) {
$user = \core_user::get_user_by_username($userdef['username']);
$this->setUser($user);
$getrecordings = $this->get_recordings($instance->get_instance_id());
// Check users see or do not see recording dependings on their groups.
foreach ($dataset['recordingsdata'] as $recordingdata) {
foreach ($recordingdata as $recording) {
if (has_capability('moodle/course:update', $context)) {
$this->assertStringContainsString('data-action=\"delete\"', $getrecordings['tabledata']['data'],
"User $user->username, should be able to delete the recording {$recording['name']}");
$this->assertStringContainsString('data-action=\"publish\"', $getrecordings['tabledata']['data'],
"User $user->username, should be able to publish the recording {$recording['name']}");
} else {
$this->assertStringNotContainsString('data-action=\"delete\"', $getrecordings['tabledata']['data'],
"User $user->username, should not be able to delete the recording {$recording['name']}");
}
}
}
}
// Now without delete.
foreach ($dataset['users'] as $userdef) {
$user = \core_user::get_user_by_username($userdef['username']);
$this->setUser($user);
$getrecordings = $this->get_recordings($instance->get_instance_id(), 'protect');
// Check users see or do not see recording dependings on their groups.
foreach ($dataset['recordingsdata'] as $recordingdata) {
foreach ($recordingdata as $recording) {
$this->assertStringNotContainsString('data-action=\"delete\"', $getrecordings['tabledata']['data'],
"User $user->username, should not be able to delete the recording {$recording['name']}");
}
}
}
}
/**
* Check preview is present and displayed
*/
public function test_get_recordings_preview(): void {
$this->resetAfterTest();
$dataset = [
'type' => instance::TYPE_ALL,
'additionalsettings' => [
'recordings_preview' => 1
],
'groups' => null,
'users' => [['username' => 't1', 'role' => 'editingteacher'], ['username' => 's1', 'role' => 'student']],
'recordingsdata' => [
[['name' => 'Recording1']],
[['name' => 'Recording2']]
],
];
$activityid = $this->create_from_dataset($dataset);
$instance = instance::get_from_instanceid($activityid);
$context = \context_course::instance($instance->get_course_id());
foreach ($dataset['users'] as $userdef) {
$user = \core_user::get_user_by_username($userdef['username']);
$this->setUser($user);
$getrecordings = $this->get_recordings($instance->get_instance_id());
$this->assertNotEmpty($getrecordings['tabledata']['columns']['3']);
$this->assertEquals('preview', $getrecordings['tabledata']['columns']['3']['key']);
}
}
/**
* Check we can see all recording from a course in a room only instance
* @covers \mod_bigbluebuttonbn\external\get_recordings::execute
*/
public function test_get_recordings_room_only(): void {
$this->resetAfterTest();
set_config('bigbluebuttonbn_importrecordings_enabled', 1);
$dataset = [
'type' => instance::TYPE_ALL,
'groups' => null,
'users' => [['username' => 't1', 'role' => 'editingteacher'], ['username' => 's1', 'role' => 'student']],
'recordingsdata' => [
[['name' => 'Recording1']],
[['name' => 'Recording2']]
],
];
$activityid = $this->create_from_dataset($dataset);
$instance = instance::get_from_instanceid($activityid);
// Now create a recording only activity.
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
// Now create a new activity and import the first record.
$newactivity = $plugingenerator->create_instance([
'course' => $instance->get_course_id(),
'type' => instance::TYPE_RECORDING_ONLY,
'name' => 'Example 2'
]);
$plugingenerator->create_meeting([
'instanceid' => $newactivity->id,
]); // We need to have a meeting created in order to import recordings.
$newinstance = instance::get_from_instanceid($newactivity->id);
$this->create_recordings_for_instance($newinstance, [['name' => 'Recording3']]);
foreach ($dataset['users'] as $userdef) {
$user = \core_user::get_user_by_username($userdef['username']);
$this->setUser($user);
$getrecordings = $this->get_recordings($newinstance->get_instance_id());
// Check users see or do not see recording dependings on their groups.
$data = json_decode($getrecordings['tabledata']['data']);
$this->assertCount(3, $data);
}
}
/**
* Check if we can see the imported recording in a new instance
* @covers \mod_bigbluebuttonbn\external\get_recordings::execute
*/
public function test_get_recordings_imported(): void {
$this->resetAfterTest();
set_config('bigbluebuttonbn_importrecordings_enabled', 1);
$dataset = [
'type' => instance::TYPE_ALL,
'groups' => null,
'users' => [['username' => 't1', 'role' => 'editingteacher'], ['username' => 's1', 'role' => 'student']],
'recordingsdata' => [
[['name' => 'Recording1']],
[['name' => 'Recording2']]
],
];
$activityid = $this->create_from_dataset($dataset);
$instance = instance::get_from_instanceid($activityid);
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
// Now create a new activity and import the first record.
$newactivity = $plugingenerator->create_instance([
'course' => $instance->get_course_id(),
'type' => instance::TYPE_ALL,
'name' => 'Example 2'
]);
$plugingenerator->create_meeting([
'instanceid' => $newactivity->id,
]); // We need to have a meeting created in order to import recordings.
$newinstance = instance::get_from_instanceid($newactivity->id);
$recordings = $instance->get_recordings();
foreach ($recordings as $recording) {
if ($recording->get('name') == 'Recording1') {
$recording->create_imported_recording($newinstance);
}
}
foreach ($dataset['users'] as $userdef) {
$user = \core_user::get_user_by_username($userdef['username']);
$this->setUser($user);
$getrecordings = $this->get_recordings($newinstance->get_instance_id());
// Check users see or do not see recording dependings on their groups.
foreach ($dataset['recordingsdata'] as $index => $recordingdata) {
foreach ($recordingdata as $recording) {
if ($instance->can_manage_recordings()) {
$this->assertStringContainsString('data-action=\"delete\"', $getrecordings['tabledata']['data'],
"User $user->username, should be able to delete the recording {$recording['name']}");
} else {
$this->assertStringNotContainsString('data-action=\"delete\"', $getrecordings['tabledata']['data'],
"User $user->username, should not be able to delete the recording {$recording['name']}");
}
if ($index === 0) {
$this->assertStringContainsString($recording['name'], $getrecordings['tabledata']['data']);
} else {
$this->assertStringNotContainsString($recording['name'], $getrecordings['tabledata']['data']);
}
}
}
}
}
/**
* Check we can see only imported recordings in a recordings only instance when "Show only imported links" enabled.
* @covers \mod_bigbluebuttonbn\external\get_recordings::execute
*/
public function test_get_imported_recordings_only(): void {
$this->resetAfterTest();
set_config('bigbluebuttonbn_importrecordings_enabled', 1);
$dataset = [
'type' => instance::TYPE_ALL,
'groups' => null,
'users' => [['username' => 's1', 'role' => 'student']],
'recordingsdata' => [
[['name' => 'Recording1']],
[['name' => 'Recording2']]
],
];
$activityid = $this->create_from_dataset($dataset);
$instance = instance::get_from_instanceid($activityid);
// Now create a recording only activity.
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
// Now create a new activity and import the first record.
$newactivity = $plugingenerator->create_instance([
'course' => $instance->get_course_id(),
'type' => instance::TYPE_RECORDING_ONLY,
'name' => 'Example 2'
]);
$plugingenerator->create_meeting([
'instanceid' => $newactivity->id,
]); // We need to have a meeting created in order to import recordings.
$newinstance = instance::get_from_instanceid($newactivity->id);
$recordings = $instance->get_recordings();
foreach ($recordings as $recording) {
if ($recording->get('name') == 'Recording1') {
$recording->create_imported_recording($newinstance);
}
}
$user = \core_user::get_user_by_username('s1');
$this->setUser($user);
$getrecordings = $this->get_recordings($newinstance->get_instance_id());
$data = json_decode($getrecordings['tabledata']['data']);
// Check that all recordings including the imported recording appear.
$this->assertCount(3, $data);
// Set the flags to enable "Show only imported links".
set_config('bigbluebuttonbn_recordings_imported_default', 1);
set_config('bigbluebuttonbn_recordings_imported_editable', 0);
$getrecordings = $this->get_recordings($newinstance->get_instance_id());
$data = json_decode($getrecordings['tabledata']['data']);
$this->assertCount(1, $data);
}
/**
* Check if recording are visible/invisible depending on the group.
*
* @param string $type
* @param array $groups
* @param array $users
* @param array $recordingsdata
* @param array $test
* @param int $coursemode
*
* @covers \mod_bigbluebuttonbn\external\get_recordings::execute
* @dataProvider recording_group_test_data
*/
public function test_get_recordings_groups($type, $groups, $users, $recordingsdata, $test, $coursemode): void {
$this->resetAfterTest();
$dataset = compact('type', 'groups', 'users', 'recordingsdata', 'test', 'coursemode');
$activityid = $this->create_from_dataset($dataset);
$instance = instance::get_from_instanceid($activityid);
foreach ($dataset['users'] as $userdef) {
$user = \core_user::get_user_by_username($userdef['username']);
$this->setUser($user);
$groups = array_values(groups_get_my_groups());
$mygroup = !empty($groups) ? end($groups) : null;
$getrecordings = $this->get_recordings(
$instance->get_instance_id(), null, !empty($mygroup) ? $mygroup->id : null);
$allrecordingsnames = [];
foreach ($recordingsdata as $groups => $rsinfo) {
$rnames = array_map(function($rdata) {
return $rdata['name'];
}, $rsinfo);
$allrecordingsnames = array_merge($allrecordingsnames, $rnames);
}
// Check users see or do not see recording dependings on their groups.
foreach ($dataset['test'][$user->username] as $viewablerecordings) {
$viewablerecordings = $dataset['test'][$user->username];
$invisiblerecordings = array_diff($allrecordingsnames, $viewablerecordings);
foreach ($viewablerecordings as $viewablerecordingname) {
$this->assertStringContainsString($viewablerecordingname, $getrecordings['tabledata']['data'],
"User $user->username, should see recording {$viewablerecordingname}");
}
foreach ($invisiblerecordings as $invisiblerecordingname) {
$this->assertStringNotContainsString($invisiblerecordingname, $getrecordings['tabledata']['data'],
"User $user->username, should not see recording {$viewablerecordingname}");
}
}
}
}
/**
* Recording group test
*
* @return array[]
*/
public function recording_group_test_data() {
return [
'visiblegroups' => [
'type' => instance::TYPE_ALL,
'groups' => ['G1' => ['s1'], 'G2' => ['s2']],
'users' => [
['username' => 't1', 'role' => 'editingteacher'],
['username' => 's1', 'role' => 'student'],
['username' => 's2', 'role' => 'student'],
['username' => 's3', 'role' => 'student']
],
'recordingsdata' => [
'G1' => [['name' => 'Recording1']],
'G2' => [['name' => 'Recording2']],
'' => [['name' => 'Recording3']]
],
'test' => [
't1' => ['Recording1', 'Recording2', 'Recording3'], // A moderator should see all recordings.
's1' => ['Recording1'], // S1 can only see the recordings from his group.
's2' => ['Recording2'], // S2 can only see the recordings from his group.
's3' => ['Recording3', 'Recording2', 'Recording1']
// S3 should see recordings which have no groups and his groups's recording.
],
'coursemode' => VISIBLEGROUPS
],
'separategroups' => [
'type' => instance::TYPE_ALL,
'groups' => ['G1' => ['s1'], 'G2' => ['s2']],
'users' => [
['username' => 't1', 'role' => 'editingteacher'],
['username' => 's1', 'role' => 'student'],
['username' => 's2', 'role' => 'student']
],
'recordingsdata' => [
'G1' => [['name' => 'Recording1']],
'G2' => [['name' => 'Recording2']],
'' => [['name' => 'Recording3']]
],
'test' => [
't1' => ['Recording1', 'Recording2', 'Recording3'], // A moderator should see all recordings.
's1' => ['Recording1'], // S1 can only see the recordings from his group.
's2' => ['Recording2'], // S2 can only see the recordings from his group.
's3' => ['Recording3'] // S3 should see recordings which have no groups.
],
'coursemode' => SEPARATEGROUPS
]
];
}
}
@@ -0,0 +1,126 @@
<?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/>.
namespace mod_bigbluebuttonbn\external;
use core_external\external_api;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\test\testcase_helper_trait;
use require_login_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Tests for the view_bigbluebuttonbn class.
*
* @package mod_bigbluebuttonbn
* @category test
* @copyright 2021 - present, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent@call-learning.fr)
* @covers \mod_bigbluebuttonbn\external\view_bigbluebuttonbn
*/
class view_bigbluebuttonbn_test extends \externallib_advanced_testcase {
use testcase_helper_trait;
/**
* Setup for test
*/
public function setUp(): void {
parent::setUp();
$this->initialise_mock_server();
}
/**
* Helper
*
* @param mixed ...$params
* @return mixed
*/
protected function view_bigbluebuttonbn(...$params) {
$returnvalue = view_bigbluebuttonbn::execute(...$params);
return external_api::clean_returnvalue(view_bigbluebuttonbn::execute_returns(), $returnvalue);
}
/**
* Test execute API CALL with no instance
*/
public function test_execute_no_instance(): void {
$this->resetAfterTest();
$bbbactivities = $this->view_bigbluebuttonbn(1234);
$this->assertIsArray($bbbactivities);
$this->assertArrayHasKey('status', $bbbactivities);
$this->assertArrayHasKey('warnings', $bbbactivities);
$this->assertFalse($bbbactivities['status']);
}
/**
* Test execute API CALL without login
*/
public function test_execute_without_login(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = $this->getDataGenerator()->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$this->expectException(require_login_exception::class);
$this->view_bigbluebuttonbn($instance->get_instance_id());
}
/**
* Test execute API CALL with invalid login
*/
public function test_execute_with_invalid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_user($course);
$this->setUser($user);
$this->expectException(require_login_exception::class);
$this->view_bigbluebuttonbn($instance->get_instance_id());
}
/**
* When login as a student
*/
public function test_execute_with_valid_login(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$record = $generator->create_module('bigbluebuttonbn', ['course' => $course->id]);
$instance = instance::get_from_instanceid($record->id);
$user = $generator->create_and_enrol($course, 'student');
$this->setUser($user);
$returnvalue = $this->view_bigbluebuttonbn($instance->get_instance_id());
$this->assertArrayHasKey('status', $returnvalue);
$this->assertArrayHasKey('warnings', $returnvalue);
$this->assertTrue($returnvalue['status']);
}
}