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
+552
View File
@@ -0,0 +1,552 @@
<?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 core_communication;
use core_communication\task\add_members_to_room_task;
use core_communication\task\create_and_configure_room_task;
use communication_matrix\matrix_test_helper_trait;
use core_communication\task\synchronise_provider_task;
use core_communication\task\synchronise_providers_task;
use core_communication\task\remove_members_from_room;
use core_communication\task\update_room_task;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/../provider/matrix/tests/matrix_test_helper_trait.php');
require_once(__DIR__ . '/communication_test_helper_trait.php');
/**
* Class api_test to test the communication public api and its associated methods.
*
* @package core_communication
* @category test
* @copyright 2023 Safat Shahin <safat.shahin@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_communication\api
*/
class api_test extends \advanced_testcase {
use matrix_test_helper_trait;
use communication_test_helper_trait;
public function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->setup_communication_configs();
$this->initialise_mock_server();
}
/**
* Test set data to the instance.
*/
public function test_set_data(): void {
$course = $this->get_course();
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
// Sample data.
$roomname = 'Sampleroom';
$provider = 'communication_matrix';
// Set the data.
$communication->set_data($course);
$roomnameidenfier = $communication->get_provider() . 'roomname';
// Test the set data.
$this->assertEquals($roomname, $course->$roomnameidenfier);
$this->assertEquals($provider, $course->selectedcommunication);
}
/**
* Test get_current_communication_provider method.
*/
public function test_get_provider(): void {
$course = $this->get_course();
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertEquals('communication_matrix', $communication->get_provider());
}
/**
* Test set_avatar method.
*/
public function test_set_avatar(): void {
global $CFG;
$this->setAdminUser();
$course = $this->get_course('Sampleroom', 'none');
// Sample data.
$communicationroomname = 'Sampleroom';
$selectedcommunication = 'communication_matrix';
$avatar = $this->create_communication_file(
'moodle_logo.jpg',
'moodle_logo.jpg',
);
// Create the room, settingthe avatar.
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
provider: $selectedcommunication,
);
$communication->create_and_configure_room($communicationroomname, $avatar);
// Reload the communication processor.
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
// Compare result.
$this->assertEquals(
$avatar->get_contenthash(),
$communicationprocessor->get_avatar()->get_contenthash(),
);
}
/**
* Test the create_and_configure_room method to add/create tasks.
*/
public function test_create_and_configure_room(): void {
// Get the course by disabling communication so that we can create it manually calling the api.
$course = $this->get_course('Sampleroom', 'none');
// Sample data.
$communicationroomname = 'Sampleroom';
$selectedcommunication = 'communication_matrix';
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
provider: $selectedcommunication,
);
$communication->create_and_configure_room($communicationroomname);
// Test the tasks added.
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\create_and_configure_room_task');
$this->assertCount(1, $adhoctask);
$adhoctask = reset($adhoctask);
$this->assertInstanceOf('\\core_communication\\task\\create_and_configure_room_task', $adhoctask);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertEquals($communicationroomname, $communicationprocessor->get_room_name());
$this->assertEquals($selectedcommunication, $communicationprocessor->get_provider());
}
/**
* Test the create_and_configure_room method to add/create tasks when no communication provider selected.
*/
public function test_create_and_configure_room_without_communication_provider_selected(): void {
// Get the course by disabling communication so that we can create it manually calling the api.
$course = $this->get_course('Sampleroom', 'none');
// Test the tasks added.
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\create_and_configure_room_task');
$this->assertCount(0, $adhoctask);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertNull($communicationprocessor);
}
/**
* Test update operation.
*/
public function test_update_room(): void {
$course = $this->get_course();
// Sample data.
$communicationroomname = 'Sampleroomupdated';
$selectedcommunication = 'communication_matrix';
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$communication->update_room(processor::PROVIDER_ACTIVE, $communicationroomname);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertEquals($communicationroomname, $communicationprocessor->get_room_name());
$this->assertEquals($selectedcommunication, $communicationprocessor->get_provider());
$this->assertTrue($communicationprocessor->is_instance_active());
$communication->update_room(processor::PROVIDER_INACTIVE, $communicationroomname);
// Test updating active state.
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
provider: $selectedcommunication,
);
$this->assertEquals($communicationroomname, $communicationprocessor->get_room_name());
$this->assertEquals($selectedcommunication, $communicationprocessor->get_provider());
$this->assertFalse($communicationprocessor->is_instance_active());
}
/**
* Test delete operation.
*/
public function test_delete_room(): void {
$course = $this->get_course();
// Sample data.
$communicationroomname = 'Sampleroom';
$selectedcommunication = 'communication_matrix';
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertEquals($communicationroomname, $communicationprocessor->get_room_name());
$this->assertEquals($selectedcommunication, $communicationprocessor->get_provider());
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$communication->delete_room();
// Test the tasks added.
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\delete_room_task');
// Should be 2 as one for create, another for update.
$this->assertCount(1, $adhoctask);
$adhoctask = reset($adhoctask);
$this->assertInstanceOf('\\core_communication\\task\\delete_room_task', $adhoctask);
}
/**
* Test the adding and removing of members from room.
*
* @covers ::add_members_to_room
* @covers ::remove_members_from_room
*/
public function test_adding_and_removing_of_room_membership(): void {
$course = $this->get_course();
$userid = $this->get_user()->id;
// First test the adding members to a room.
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$communication->add_members_to_room([$userid]);
// Test the tasks added.
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\add_members_to_room_task');
$this->assertCount(1, $adhoctask);
// Now test the removing members from a room.
$communication->remove_members_from_room([$userid]);
// Test the tasks added.
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\remove_members_from_room');
$this->assertCount(1, $adhoctask);
}
/**
* Test the update of room membership with the change user role.
*
* @covers ::update_room_membership
*/
public function test_update_room_membership_on_user_role_change(): void {
global $DB;
// Generate the data.
$user = $this->getDataGenerator()->create_user();
$course = $this->get_course();
$coursecontext = \context_course::instance($course->id);
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$this->getDataGenerator()->enrol_user($user->id, $course->id);
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\add_members_to_room_task');
$this->assertCount(1, $adhoctask);
$adhoctask = reset($adhoctask);
$this->assertInstanceOf('\\core_communication\\task\\add_members_to_room_task', $adhoctask);
// Test the tasks added as the role is a teacher.
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\update_room_membership_task');
$this->assertCount(1, $adhoctask);
$adhoctask = reset($adhoctask);
$this->assertInstanceOf('\\core_communication\\task\\update_room_membership_task', $adhoctask);
}
/**
* Test sync_provider method for the sync of available provider.
*
* @covers ::sync_provider
*/
public function test_sync_provider(): void {
// Generate the data.
$user = $this->getDataGenerator()->create_user();
$course1 = $this->get_course();
$this->getDataGenerator()->enrol_user($user->id, $course1->id);
$course2 = $this->get_course();
$this->getDataGenerator()->enrol_user($user->id, $course2->id);
// Now run the task to add sync providers.
$this->execute_task(synchronise_providers_task::class);
$adhoctask = \core\task\manager::get_adhoc_tasks(synchronise_provider_task::class);
$this->assertCount(2, $adhoctask);
}
/**
* Test the removal of all members from the room.
*
* @covers ::remove_all_members_from_room
*/
public function test_remove_all_members_from_room(): void {
$course = $this->get_course();
$userid = $this->get_user()->id;
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$communication->add_members_to_room([$userid]);
// Now test the removing members from a room.
$communication->remove_all_members_from_room();
// Test the remove members tasks added.
$adhoctask = \core\task\manager::get_adhoc_tasks(remove_members_from_room::class);
$this->assertCount(1, $adhoctask);
}
/**
* Test the configuration of room changes as well as the membership with the change of provider.
*
* @covers ::configure_room_and_membership_by_provider
*/
public function test_configure_room_and_membership_by_provider(): void {
global $DB;
$course = $this->get_course('Sampleroom', 'none');
$userid = $this->get_user()->id;
$provider = 'communication_matrix';
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$communication->configure_room_and_membership_by_provider(
provider: $provider,
instance: $course,
communicationroomname: $course->fullname,
users: [$userid],
);
$communication->reload();
// Test that the task to create a room is added.
$adhoctask = \core\task\manager::get_adhoc_tasks(create_and_configure_room_task::class);
$this->assertCount(1, $adhoctask);
// Test that no update tasks are added.
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(0, $adhoctask);
// Test that the task to add members to room is not added, as we are adding the user mapping not the task.
$adhoctask = \core\task\manager::get_adhoc_tasks(add_members_to_room_task::class);
$this->assertCount(0, $adhoctask);
// Now delete all the ad-hoc tasks.
$DB->delete_records('task_adhoc');
// Now disable the provider by setting none.
$communication->configure_room_and_membership_by_provider(
provider: processor::PROVIDER_NONE,
instance: $course,
communicationroomname: $course->fullname,
users: [$userid],
);
$communication->reload();
// Test that the task to delete a room is added.
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(1, $adhoctask);
// Test that the task to remove members from room is added.
$adhoctask = \core\task\manager::get_adhoc_tasks(remove_members_from_room::class);
$this->assertCount(1, $adhoctask);
// Now delete all the ad-hoc tasks.
$DB->delete_records('task_adhoc');
// Now try to set the same none provider again.
$communication->configure_room_and_membership_by_provider(
provider: processor::PROVIDER_NONE,
instance: $course,
communicationroomname: $course->fullname,
users: [$userid],
);
// Test that no communicaiton task is added.
$adhoctask = \core\task\manager::get_adhoc_tasks(create_and_configure_room_task::class);
$this->assertCount(0, $adhoctask);
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(0, $adhoctask);
$adhoctask = \core\task\manager::get_adhoc_tasks(add_members_to_room_task::class);
$this->assertCount(0, $adhoctask);
$adhoctask = \core\task\manager::get_adhoc_tasks(remove_members_from_room::class);
$this->assertCount(0, $adhoctask);
// Now let's change it back to matrix and test the update task is added.
$communication->configure_room_and_membership_by_provider(
provider: $provider,
instance: $course,
communicationroomname: $course->fullname,
users: [$userid],
);
$communication->reload();
// Test create task is not added because communication has been created in the past.
$adhoctask = \core\task\manager::get_adhoc_tasks(create_and_configure_room_task::class);
$this->assertCount(0, $adhoctask);
// Test an update task added.
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(1, $adhoctask);
// Test add membership task is added.
$adhoctask = \core\task\manager::get_adhoc_tasks(add_members_to_room_task::class);
$this->assertCount(1, $adhoctask);
// Now delete all the ad-hoc tasks.
$DB->delete_records('task_adhoc');
$course->customlinkurl = $course->customlinkurl ?? 'https://moodle.org';
// Now change the provider to another one.
$communication->configure_room_and_membership_by_provider(
provider: 'communication_customlink',
instance: $course,
communicationroomname: $course->fullname,
users: [$userid],
);
$communication->reload();
// Remove membership and update room task for the previous provider.
// Create room task for new one.
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(1, $adhoctask);
$adhoctask = \core\task\manager::get_adhoc_tasks(remove_members_from_room::class);
$this->assertCount(1, $adhoctask);
$adhoctask = \core\task\manager::get_adhoc_tasks(create_and_configure_room_task::class);
$this->assertCount(1, $adhoctask);
// Now delete all the ad-hoc tasks.
$DB->delete_records('task_adhoc');
// Now disable the provider.
$communication->configure_room_and_membership_by_provider(
provider: processor::PROVIDER_NONE,
instance: $course,
communicationroomname: $course->fullname,
users: [$userid],
);
$communication->reload();
// Should have one update and one remove task.
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(1, $adhoctask);
// This provider doesn't have any membership, so no remove task.
$adhoctask = \core\task\manager::get_adhoc_tasks(remove_members_from_room::class);
$this->assertCount(0, $adhoctask);
// Now delete all the ad-hoc tasks.
$DB->delete_records('task_adhoc');
// Now enable the same provider again.
$communication->configure_room_and_membership_by_provider(
provider: $provider,
instance: $course,
communicationroomname: $course->fullname,
users: [$userid],
);
// Now it should have one update and one add task.
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(1, $adhoctask);
$adhoctask = \core\task\manager::get_adhoc_tasks(add_members_to_room_task::class);
$this->assertCount(1, $adhoctask);
}
}
@@ -0,0 +1,50 @@
<?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/>.
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
require_once(__DIR__ . '/../../tests/communication_test_helper_trait.php');
/**
* Class behat_communication for behat custom steps and configuration for communication api.
*
* @package core_communication
* @category test
* @copyright 2023 Safat Shahin <safat.shahin@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_communication extends \behat_base {
use \core_communication\communication_test_helper_trait;
/**
* Configure and enable communication experimental feature.
*
* @Given /^I enable communication experimental feature$/
*/
public function enable_communication_experimental_feature(): void {
$this->setup_communication_configs();
}
/**
* Disable communication experimental feature.
*
* @Given /^I disable communication experimental feature$/
*/
public function disable_communication_experimental_feature(): void {
$this->disable_communication_configs();
}
}
@@ -0,0 +1,109 @@
@communication
Feature: Access the communication configuration page
As an editing teacher
See dynamic form fields based on selected provider
Background: Set up teachers and course for the communication confifiguration page
Given I enable communication experimental feature
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| teacher2 | Teacher | 2 | teacher2@example.com |
And the following "courses" exist:
| fullname | shortname | category | selectedcommunication |
| Test course | Test course | 0 | none |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | Test course | editingteacher |
| teacher2 | Test course | teacher |
Scenario: A teacher with the correct capability can access the communication configuration page
Given I am on the "Test course" "Course" page logged in as "teacher1"
When I navigate to "Communication" in current page administration
Then I should see "Communication"
Scenario: A teacher without the correct capability cannot access the communication configuration page
Given I am on the "Test course" "Course" page logged in as "teacher2"
Then "Communication" "link" should not exist in current page administration
Scenario: I cannot see the communication link when communication provider is disabled
Given I disable communication experimental feature
And I am on the "Test course" "Course" page logged in as "teacher1"
Then "Communication" "link" should not exist in current page administration
@javascript
Scenario: The communication form fields toggle dynamically when valid provider is set
Given a Matrix mock server is configured
And I am on the "Test course" "Course" page logged in as "teacher1"
When I navigate to "Communication" in current page administration
And I set the following fields to these values:
| selectedcommunication | communication_matrix |
And I wait to be redirected
Then I should see "Room name"
And I should see "Room topic"
@javascript
Scenario: Changing the communication provider in the form fetches the correct data
Given a Matrix mock server is configured
And I am on the "Test course" "Course" page logged in as "teacher1"
When I navigate to "Communication" in current page administration
And I set the following fields to these values:
| selectedcommunication | communication_matrix |
And I wait to be redirected
And I should see "Room name"
And I should see "Room topic"
And I set the following fields to these values:
| communication_matrixroomname | Matrix room |
| matrixroomtopic | Matrix topic |
And I click on "Save changes" "button"
And I navigate to "Communication" in current page administration
Then the field "Room name" matches value "Matrix room"
And the field "Room topic" matches value "Matrix topic"
And I set the following fields to these values:
| selectedcommunication | communication_customlink |
And I wait to be redirected
And I should see "Room name"
And I should not see "Room topic"
And I should see "Custom link URL"
And I set the following fields to these values:
| communication_customlinkroomname | Custom link room |
| customlinkurl | https://moodle.org |
And I click on "Save changes" "button"
And I navigate to "Communication" in current page administration
And the field "Room name" matches value "Custom link room"
And the field "Custom link URL" matches value "https://moodle.org"
And I set the following fields to these values:
| selectedcommunication | communication_matrix |
And I wait to be redirected
And I should see "Room name"
And I should see "Room topic"
And the field "Room name" matches value "Matrix room"
And the field "Room topic" matches value "Matrix topic"
And I should not see "Custom link URL"
And I set the following fields to these values:
| selectedcommunication | communication_customlink |
And I wait to be redirected
And I should see "Room name"
And I should see "Custom link URL"
And the field "Room name" matches value "Custom link room"
And the field "Custom link URL" matches value "https://moodle.org"
And I should not see "Room topic"
And I set the following fields to these values:
| selectedcommunication | communication_matrix |
And I wait to be redirected
And I click on "Save changes" "button"
And I am on "Test course" course homepage with editing mode on
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Group mode | Separate groups |
And I press "Save and display"
And I navigate to "Communication" in current page administration
And the field "Room name" matches value "Matrix room"
And the field "Room topic" matches value "Matrix topic"
And I press "Cancel"
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Group mode | Visible groups |
And I navigate to "Communication" in current page administration
And the field "Room name" matches value "Matrix room"
And the field "Room topic" matches value "Matrix topic"
@@ -0,0 +1,131 @@
<?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 core_communication;
/**
* Trait communication_test_helper_trait to generate initial setup for communication providers.
*
* @package core_communication
* @category test
* @copyright 2023 Safat Shahin <safat.shahin@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
trait communication_test_helper_trait {
/**
* Setup necessary configs for communication subsystem.
*
* @return void
*/
protected function setup_communication_configs(): void {
set_config('enablecommunicationsubsystem', 1);
}
/**
* Disable configs for communication subsystem.
*
* @return void
*/
protected function disable_communication_configs(): void {
set_config('enablecommunicationsubsystem', 0);
}
/**
* Get or create course if it does not exist
*
* @param string $roomname The room name for the communication api
* @param string $provider The selected provider
* @return \stdClass
*/
protected function get_course(
string $roomname = 'Sampleroom',
string $provider = 'communication_matrix',
array $extrafields = [],
): \stdClass {
$this->setup_communication_configs();
$records = [
'selectedcommunication' => $provider,
'communicationroomname' => $roomname,
];
return $this->getDataGenerator()->create_course(array_merge($records, $extrafields));
}
/**
* Get or create user if it does not exist.
*
* @param string $firstname The user's firstname for the communication api
* @param string $lastname The user's lastname for the communication api
* @param string $username The user's username for the communication api
* @return \stdClass
*/
protected function get_user(
string $firstname = 'Samplefn',
string $lastname = 'Sampleln',
string $username = 'sampleun'
): \stdClass {
$this->setup_communication_configs();
$records = [
'firstname' => $firstname,
'lastname' => $lastname,
'username' => $username,
];
return $this->getDataGenerator()->create_user($records);
}
/**
* Create a stored_file in a draft file area from a fixture file.
*
* @param string $filename The file name within the communication/tests/fixtures folder.
* @param string $storedname The name to use in the database.
* @return \stored_file
*/
protected function create_communication_file(
string $filename,
string $storedname,
): \stored_file {
global $CFG;
$fs = get_file_storage();
$itemid = file_get_unused_draft_itemid();
return $fs->create_file_from_pathname((object) [
'contextid' => \context_system::instance()->id,
'component' => 'user',
'filearea' => 'draftfile',
'itemid' => $itemid,
'filepath' => '/',
'filename' => $storedname,
], "{$CFG->dirroot}/communication/tests/fixtures/{$filename}");
}
/**
* Helper to execute a particular task.
*
* @param string $task The task.
*/
private function execute_task(string $task): void {
// Run the scheduled task.
ob_start();
$task = \core\task\manager::get_scheduled_task($task);
$task->execute();
ob_end_clean();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

+234
View File
@@ -0,0 +1,234 @@
<?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 core_communication;
use communication_matrix\matrix_test_helper_trait;
use core_communication\processor as communication_processor;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/../provider/matrix/tests/matrix_test_helper_trait.php');
require_once(__DIR__ . '/communication_test_helper_trait.php');
/**
* Test communication helper methods.
*
* @package core_communication
* @copyright 2023 Safat Shahin <safat.shahin@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_communication\helper
*/
class helper_test extends \advanced_testcase {
use communication_test_helper_trait;
use matrix_test_helper_trait;
public function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->setup_communication_configs();
$this->initialise_mock_server();
}
/**
* Test load_by_group.
*/
public function test_load_by_group(): void {
// As communication is created by default.
$course = $this->get_course(
extrafields: ['groupmode' => SEPARATEGROUPS],
);
$group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
$context = \context_course::instance(courseid: $course->id);
$groupcommunication = helper::load_by_group(
groupid: $group->id,
context: $context,
);
$this->assertInstanceOf(
expected: communication_processor::class,
actual: $groupcommunication->get_processor(),
);
}
/**
* Test load_by_course.
*/
public function test_load_by_course(): void {
// As communication is created by default.
$course = $this->get_course();
$coursecontext = \context_course::instance(courseid: $course->id);
$coursecommunication = helper::load_by_course(
courseid: $course->id,
context: $coursecontext,
);
$this->assertInstanceOf(
expected: communication_processor::class,
actual: $coursecommunication->get_processor(),
);
}
/**
* Test get_access_to_all_group_cap_users.
*/
public function test_get_users_has_access_to_all_groups(): void {
global $DB;
// Set up the data with course, group, user etc.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$course = $this->get_course();
$coursecontext = \context_course::instance(courseid: $course->id);
// Enrol user1 as teacher.
$teacherrole = $DB->get_record(
table: 'role',
conditions: ['shortname' => 'manager'],
);
$this->getDataGenerator()->enrol_user(
userid: $user1->id,
courseid: $course->id,
);
role_assign(
roleid: $teacherrole->id,
userid: $user1->id,
contextid: $coursecontext->id,
);
// Enrol user2 as student.
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
$this->getDataGenerator()->enrol_user(
userid: $user2->id,
courseid: $course->id,
);
role_assign(
roleid: $studentrole->id,
userid: $user2->id,
contextid: $coursecontext->id,
);
$allgroupaccessusers = helper::get_users_has_access_to_all_groups(
userids: [$user1->id, $user2->id],
courseid: $course->id,
);
$this->assertContains(
needle: $user1->id,
haystack: $allgroupaccessusers,
);
$this->assertNotContains(
needle: $user2->id,
haystack: $allgroupaccessusers,
);
}
/**
* Test update_communication_room_membership.
*/
public function test_update_communication_room_membership(): void {
global $DB;
// Set up the data with course, group, user etc.
$user = $this->getDataGenerator()->create_user();
$course = $this->get_course();
$coursecontext = \context_course::instance(courseid: $course->id);
$teacherrole = $DB->get_record(
table: 'role',
conditions: ['shortname' => 'manager'],
);
$this->getDataGenerator()->enrol_user(
userid: $user->id,
courseid: $course->id,
);
role_assign(
roleid: $teacherrole->id,
userid:$user->id,
contextid: $coursecontext->id,
);
// Now remove members from room.
helper::update_course_communication_room_membership(
course: $course,
userids: [$user->id],
memberaction: 'remove_members_from_room',
);
// Now test that there is communication instances for the course and the user removed from that instance.
$coursecommunication = helper::load_by_course(
courseid: $course->id,
context: $coursecontext,
);
// Check the user is added for course communication instance.
$courseusers = $coursecommunication->get_processor()->get_all_delete_flagged_userids();
$courseusers = reset($courseusers);
$this->assertEquals(
expected: $user->id,
actual: $courseusers,
);
// Now add members to room.
helper::update_course_communication_room_membership(
course: $course,
userids: [$user->id],
memberaction: 'add_members_to_room',
);
$coursecommunication->reload();
// Check the user is added for course communication instance.
$courseusers = $coursecommunication->get_processor()->get_instance_userids();
$courseusers = reset($courseusers);
$this->assertEquals(
expected: $user->id,
actual: $courseusers,
);
// Now update membership.
helper::update_course_communication_room_membership(
course: $course,
userids: [$user->id],
memberaction: 'update_room_membership',
);
$coursecommunication->reload();
// Check the user is added for course communication instance.
$courseusers = $coursecommunication->get_processor()->get_instance_userids();
$courseusers = reset($courseusers);
$this->assertEquals(
expected: $user->id,
actual: $courseusers,
);
// Now try using invalid action.
$this->expectException('coding_exception');
$this->expectExceptionMessage('Invalid action provided.');
helper::update_course_communication_room_membership(
course: $course,
userids: [$user->id],
memberaction: 'a_funny_action',
);
}
/**
* Test format_group_room_name.
*/
public function test_format_group_room_name(): void {
$baseroomname = 'Course A';
$groupname = 'Group 1';
$formattedroomname = helper::format_group_room_name($baseroomname, $groupname);
// Check the room name is formatted as expected.
$this->assertEquals('Group 1 (Course A)', $formattedroomname);
}
}
+628
View File
@@ -0,0 +1,628 @@
<?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 core_communication;
use communication_matrix\matrix_test_helper_trait;
use core_communication\task\add_members_to_room_task;
use core_communication\task\create_and_configure_room_task;
use core_communication\task\delete_room_task;
use core_communication\task\update_room_membership_task;
use core_communication\task\update_room_task;
use core_communication\processor as communication_processor;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/../provider/matrix/tests/matrix_test_helper_trait.php');
require_once(__DIR__ . '/communication_test_helper_trait.php');
/**
* Test communication hook listeners.
*
* @package core_communication
* @copyright 2023 Safat Shahin <safat.shahin@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_communication\hook_listener
*/
class hook_listener_test extends \advanced_testcase {
use communication_test_helper_trait;
use matrix_test_helper_trait;
public function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->setup_communication_configs();
$this->initialise_mock_server();
}
/**
* Test create_group_communication.
*/
public function test_create_update_delete_group_communication(): void {
global $DB;
$course = $this->get_course(
roomname: 'Test room name',
extrafields: ['groupmode' => SEPARATEGROUPS],
);
$coursecontext = \context_course::instance(courseid: $course->id);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
// Enrol user1 as teacher.
$teacherrole = $DB->get_record(
table: 'role',
conditions: ['shortname' => 'manager'],
);
$this->getDataGenerator()->enrol_user(
userid: $user1->id,
courseid: $course->id,
);
role_assign(
roleid: $teacherrole->id,
userid: $user1->id,
contextid: $coursecontext->id,
);
// Enrol user2 as student.
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
$this->getDataGenerator()->enrol_user(
userid: $user2->id,
courseid: $course->id,
);
role_assign(
roleid: $studentrole->id,
userid: $user2->id,
contextid: $coursecontext->id,
);
$group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
$context = \context_course::instance($course->id);
$groupcommunication = helper::load_by_group(
groupid: $group->id,
context: $context,
);
$this->assertInstanceOf(
expected: communication_processor::class,
actual: $groupcommunication->get_processor(),
);
$this->assertEquals(
expected: $group->id,
actual: $groupcommunication->get_processor()->get_instance_id(),
);
// Task to create room should be added.
$adhoctask = \core\task\manager::get_adhoc_tasks(create_and_configure_room_task::class);
$this->assertCount(1, $adhoctask);
// Task to add members to room should not be there as the room is yet to be created.
$adhoctask = \core\task\manager::get_adhoc_tasks(add_members_to_room_task::class);
$this->assertCount(0, $adhoctask);
// Only users with access to all groups should be added to the room at this point.
$groupcommunicationusers = $groupcommunication->get_processor()->get_all_userids_for_instance();
$this->assertEquals(
expected: [$user1->id],
actual: $groupcommunicationusers,
);
// Now delete all the ad-hoc tasks.
$DB->delete_records('task_adhoc');
// Now cann the update group but don't change the group name.
groups_update_group($group);
// No task should be added as nothing changed.
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(0, $adhoctask);
// Now change the group name.
$group->name = 'Changed group name';
groups_update_group($group);
// Now one task should be there to update the group room name.
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_task::class);
$this->assertCount(1, $adhoctask);
$groupcommunication->reload();
$this->assertEquals(
expected: 'Changed group name (Test room name)',
actual: $groupcommunication->get_processor()->get_room_name(),
);
// Now delete the group.
groups_delete_group($group->id);
$adhoctask = \core\task\manager::get_adhoc_tasks(delete_room_task::class);
$this->assertCount(1, $adhoctask);
}
/**
* Test inactive users are not included when being mapped to a new communication instance.
*/
public function test_inactive_users_are_not_mapped_to_new_communication(): void {
// Create a course without a communication provider set.
$course = $this->getDataGenerator()->create_course();
// Enrol some users that are both active and inactive (suspended).
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user(
userid: $user1->id,
courseid: $course->id,
roleidorshortname: 'teacher',
);
$this->getDataGenerator()->enrol_user(
userid: $user2->id,
courseid: $course->id,
roleidorshortname: 'student',
);
$this->getDataGenerator()->enrol_user(
userid: $user3->id,
courseid: $course->id,
roleidorshortname: 'teacher',
status: ENROL_USER_SUSPENDED,
);
$this->getDataGenerator()->enrol_user(
userid: $user4->id,
courseid: $course->id,
roleidorshortname: 'student',
status: ENROL_USER_SUSPENDED,
);
// Set Matrix as the communication provider and update.
$course->selectedcommunication = 'communication_matrix';
$course->communication_matrixroomname = 'testroom';
update_course($course);
helper::update_course_communication_instance(
course: $course,
changesincoursecat: false,
);
// Load the communication instance and check that only the 2 active users are returned.
$communication = helper::load_by_course(
courseid: $course->id,
context: \context_course::instance($course->id),
);
$userids = $communication->get_processor()->get_all_userids_for_instance();
$this->assertEquals(
expected: 2,
actual: count($userids),
);
$this->assertContains(
needle: $user1->id,
haystack: $userids,
);
$this->assertContains(
needle: $user2->id,
haystack: $userids,
);
}
/**
* Test inactive users are not included when being mapped to a new communication instance using groups.
*/
public function test_inactive_users_are_not_mapped_to_new_group_communication(): void {
// Create a course without a communication provider set.
$course = $this->getDataGenerator()->create_course(
options: ['groupmode' => SEPARATEGROUPS],
);
// Enrol some users that are both active and inactive (suspended).
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user(
userid: $user1->id,
courseid: $course->id,
roleidorshortname: 'teacher',
);
$this->getDataGenerator()->enrol_user(
userid: $user2->id,
courseid: $course->id,
roleidorshortname: 'student',
);
$this->getDataGenerator()->enrol_user(
userid: $user3->id,
courseid: $course->id,
roleidorshortname: 'teacher',
status: ENROL_USER_SUSPENDED,
);
$this->getDataGenerator()->enrol_user(
userid: $user4->id,
courseid: $course->id,
roleidorshortname: 'student',
status: ENROL_USER_SUSPENDED,
);
// Create a group and add all users to it.
$group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
groups_add_member(
grouporid: $group,
userorid: $user1,
);
groups_add_member(
grouporid: $group,
userorid: $user2,
);
groups_add_member(
grouporid: $group,
userorid: $user3,
);
groups_add_member(
grouporid: $group,
userorid: $user4,
);
// Set Matrix as the communication provider and update.
$course->selectedcommunication = 'communication_matrix';
$course->communication_matrixroomname = 'testroom';
update_course($course);
helper::update_group_communication_instances_for_course(
course: $course,
provider: 'communication_matrix',
);
// Load the communication instance and check that only the 2 active users are returned.
$communication = helper::load_by_group(
groupid: $group->id,
context: \context_course::instance($course->id),
);
$userids = $communication->get_processor()->get_all_userids_for_instance();
$this->assertEquals(
expected: 2,
actual: count($userids),
);
$this->assertContains(
needle: $user1->id,
haystack: $userids,
);
$this->assertContains(
needle: $user2->id,
haystack: $userids,
);
}
/**
* Test add_members_to_group_room.
*/
public function test_add_members_to_group_room(): void {
global $DB;
$course = $this->get_course(
extrafields: ['groupmode' => SEPARATEGROUPS],
);
$coursecontext = \context_course::instance(courseid: $course->id);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
// Enrol user1 as teacher.
$teacherrole = $DB->get_record(
table: 'role',
conditions: ['shortname' => 'manager'],
);
$this->getDataGenerator()->enrol_user(
userid: $user1->id,
courseid: $course->id,
);
role_assign(
roleid: $teacherrole->id,
userid: $user1->id,
contextid: $coursecontext->id,
);
// Enrol user2 as student.
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
$this->getDataGenerator()->enrol_user(
userid: $user2->id,
courseid: $course->id,
);
role_assign(
roleid: $studentrole->id,
userid: $user2->id,
contextid: $coursecontext->id,
);
$group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
// Now check if the teacher is added to the group room as the teacher has access to all groups.
$context = \context_course::instance($course->id);
$groupcommunication = helper::load_by_group(
groupid: $group->id,
context: $context,
);
// Now the communication instance should not have the student added yet.
$this->assertNotContains(
needle: $user2->id,
haystack: $groupcommunication->get_processor()->get_all_userids_for_instance(),
);
groups_add_member(
grouporid: $group,
userorid: $user2,
);
// Now it should have the student.
$this->assertContains(
needle: $user2->id,
haystack: $groupcommunication->get_processor()->get_all_userids_for_instance(),
);
}
/**
* Test if the course instances are created properly for course default provider.
*/
public function test_course_default_provider(): void {
$defaultprovider = 'communication_matrix';
// Set the default communication for course.
set_config(
name: 'coursecommunicationprovider',
value: $defaultprovider,
plugin: 'moodlecourse',
);
// Test that the default communication is created for course mode.
$course = $this->get_course();
$coursecontext = \context_course::instance(courseid: $course->id);
$coursecommunication = helper::load_by_course(
courseid: $course->id,
context: $coursecontext,
);
$this->assertEquals(
expected: $defaultprovider,
actual: $coursecommunication->get_provider(),
);
$this->assertEquals(
expected: 'core_course',
actual: $coursecommunication->get_processor()->get_component(),
);
$this->assertEquals(
expected: $course->id,
actual: $coursecommunication->get_processor()->get_instance_id(),
);
}
/**
* Test update_course_communication.
*/
public function test_update_course_communication(): void {
global $DB;
// Set up the data with course, group, user etc.
$user = $this->getDataGenerator()->create_user();
$course = $this->get_course();
$group = $this->getDataGenerator()->create_group(record: ['courseid' => $course->id]);
$coursecontext = \context_course::instance(courseid: $course->id);
$teacherrole = $DB->get_record(
table: 'role',
conditions: ['shortname' => 'teacher'],
);
$this->getDataGenerator()->enrol_user(
userid: $user->id,
courseid: $course->id,
);
role_assign(
roleid: $teacherrole->id,
userid: $user->id,
contextid: $coursecontext->id,
);
groups_add_member(
grouporid: $group->id,
userorid: $user->id,
);
// Now test that there is communication instances for the course and the user added for that instance.
$coursecommunication = helper::load_by_course(
courseid: $course->id,
context: $coursecontext,
);
$this->assertInstanceOf(
expected: communication_processor::class,
actual: $coursecommunication->get_processor(),
);
// Check the user is added for course communication instance.
$courseusers = $coursecommunication->get_processor()->get_all_userids_for_instance();
$courseusers = reset($courseusers);
$this->assertEquals(
expected: $user->id,
actual: $courseusers,
);
// Group should not have any instance yet.
$groupcommunication = helper::load_by_group(
groupid: $group->id,
context: $coursecontext,
);
$this->assertNull(actual: $groupcommunication->get_processor());
// Now update the course.
$course->groupmode = SEPARATEGROUPS;
$course->selectedcommunication = 'communication_matrix';
update_course(data: $course);
// Now there should be a group communication instance.
$groupcommunication->reload();
$this->assertInstanceOf(
expected: communication_processor::class,
actual: $groupcommunication->get_processor(),
);
// The course communication instance must be active.
$coursecommunication->reload();
$this->assertInstanceOf(
expected: communication_processor::class,
actual: $coursecommunication->get_processor(),
);
// All the course instance users must be marked as deleted.
$coursecommunication->reload();
$courseusers = $coursecommunication->get_processor()->get_all_delete_flagged_userids();
$courseusers = reset($courseusers);
$this->assertEquals(
expected: $user->id,
actual: $courseusers,
);
// Group instance should have the user.
$groupusers = $groupcommunication->get_processor()->get_all_userids_for_instance();
$groupusers = reset($groupusers);
$this->assertEquals(
expected: $user->id,
actual: $groupusers,
);
// Now disable the communication instance for the course.
$course->selectedcommunication = communication_processor::PROVIDER_NONE;
update_course(data: $course);
// Now both course and group instance should be disabled.
$coursecommunication->reload();
$this->assertNull(actual: $coursecommunication->get_processor());
$groupcommunication->reload();
$this->assertNull(actual: $groupcommunication->get_processor());
}
/**
* Test create_course_communication_instance.
*/
public function test_create_course_communication_instance(): void {
$course = $this->get_course();
$coursecontext = \context_course::instance(courseid: $course->id);
$coursecommunication = helper::load_by_course(
courseid: $course->id,
context: $coursecontext,
);
$processor = $coursecommunication->get_processor();
$this->assertEquals(
expected: 'communication_matrix',
actual: $processor->get_provider(),
);
$this->assertEquals(
expected: 'Sampleroom',
actual: $processor->get_room_name(),
);
}
/**
* Test delete_course_communication.
*/
public function test_delete_course_communication(): void {
$course = $this->get_course();
delete_course(
courseorid: $course,
showfeedback: false,
);
$adhoctask = \core\task\manager::get_adhoc_tasks(delete_room_task::class);
$this->assertCount(1, $adhoctask);
}
/**
* Test update of room membership when user changes occur.
*/
public function test_update_user_room_memberships(): void {
global $DB;
$user = $this->getDataGenerator()->create_user();
$course = $this->get_course();
$coursecontext = \context_course::instance($course->id);
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$this->getDataGenerator()->enrol_user($user->id, $course->id);
role_assign($teacherrole->id, $user->id, $coursecontext->id);
$coursecommunication = helper::load_by_course($course->id, $coursecontext);
$courseusers = $coursecommunication->get_processor()->get_all_userids_for_instance();
$courseusers = reset($courseusers);
$this->assertEquals($user->id, $courseusers);
$user->suspended = 1;
user_update_user($user, false);
$coursecommunication->reload();
$courseusers = $coursecommunication->get_processor()->get_all_delete_flagged_userids();
$courseusers = reset($courseusers);
$this->assertEquals($user->id, $courseusers);
}
/**
* Test deletion of user room memberships when a user is deleted.
*/
public function test_delete_user_room_memberships(): void {
global $DB;
$user = $this->getDataGenerator()->create_user();
$course = $this->get_course();
$coursecontext = \context_course::instance($course->id);
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$this->getDataGenerator()->enrol_user($user->id, $course->id);
role_assign($teacherrole->id, $user->id, $coursecontext->id);
delete_user($user);
$coursecommunication = helper::load_by_course($course->id, $coursecontext);
$courseusers = $coursecommunication->get_processor()->get_all_userids_for_instance();
$this->assertEmpty($courseusers);
}
/**
* Test user room membership updates with role changes in a course.
*/
public function test_update_user_membership_for_role_changes(): void {
global $DB;
$user = $this->getDataGenerator()->create_user();
$course = $this->get_course();
$coursecontext = \context_course::instance($course->id);
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$this->getDataGenerator()->enrol_user($user->id, $course->id);
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_membership_task::class);
$this->assertCount(1, $adhoctask);
role_assign($teacherrole->id, $user->id, $coursecontext->id);
$adhoctask = \core\task\manager::get_adhoc_tasks(update_room_membership_task::class);
$this->assertCount(2, $adhoctask);
}
}
+543
View File
@@ -0,0 +1,543 @@
<?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 core_communication;
use communication_matrix\matrix_test_helper_trait;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/../provider/matrix/tests/matrix_test_helper_trait.php');
require_once(__DIR__ . '/communication_test_helper_trait.php');
/**
* Class processor_test to test the communication internal api and its associated methods.
*
* @package core_communication
* @category test
* @copyright 2023 Safat Shahin <safat.shahin@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core_communication\processor
*/
class processor_test extends \advanced_testcase {
use matrix_test_helper_trait;
use communication_test_helper_trait;
public function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->setup_communication_configs();
$this->initialise_mock_server();
}
/**
* Test create instance.
*
* @covers ::create_instance
* @covers ::get_id
* @covers ::get_instance
* @covers ::get_room_name
*/
public function test_create_instance(): void {
global $DB;
$this->resetAfterTest();
// Sample test data.
$instanceid = 10;
$context = \core\context\system::instance();
$component = 'core';
$instancetype = 'mycommunication';
$selectedcommunication = 'communication_matrix';
$communicationroomname = 'communicationroom';
$communicationprocessor = processor::create_instance(
$context,
$selectedcommunication,
$instanceid,
$component,
$instancetype,
$communicationroomname,
);
// Now test the record against the database.
$communicationrecord = $DB->get_record(
'communication',
['instanceid' => $instanceid, 'component' => $component, 'instancetype' => $instancetype]
);
// Test against the set data.
$this->assertNotEmpty($communicationrecord);
$this->assertEquals($context->id, $communicationrecord->contextid);
$this->assertEquals($instanceid, $communicationrecord->instanceid);
$this->assertEquals($component, $communicationrecord->component);
$this->assertEquals($selectedcommunication, $communicationrecord->provider);
$this->assertEquals($communicationroomname, $communicationrecord->roomname);
$this->assertEquals($instancetype, $communicationrecord->instancetype);
// Test against the object.
$this->assertEquals($context->id, $communicationprocessor->get_context_id());
$this->assertEquals($context, $communicationprocessor->get_context());
$this->assertEquals($communicationprocessor->get_id(), $communicationrecord->id);
$this->assertEquals($communicationprocessor->get_provider(), $communicationrecord->provider);
$this->assertEquals($communicationprocessor->get_room_name(), $communicationrecord->roomname);
}
/**
* Test update instance.
*
* @covers ::update_instance
* @covers ::is_instance_active
* @covers ::get_id
* @covers ::get_room_name
*/
public function test_update_instance(): void {
global $DB;
$this->resetAfterTest();
// Sameple test data.
$instanceid = 10;
$context = \core\context\system::instance();
$component = 'core';
$instancetype = 'mycommunication';
$selectedcommunication = 'communication_matrix';
$communicationroomname = 'communicationroom';
$communicationprocessor = processor::create_instance(
$context,
$selectedcommunication,
$instanceid,
$component,
$instancetype,
$communicationroomname,
);
$selectedcommunication = 'none';
$communicationroomname = 'communicationroomedited';
$communicationprocessor->update_instance(processor::PROVIDER_INACTIVE, $communicationroomname);
// Now test the record against the database.
$communicationrecord = $DB->get_record('communication', [
'instanceid' => $instanceid,
'component' => $component,
'instancetype' => $instancetype,
]);
// Test against the set data.
$this->assertNotEmpty($communicationrecord);
$this->assertEquals($context->id, $communicationrecord->contextid);
$this->assertEquals($instanceid, $communicationrecord->instanceid);
$this->assertEquals($component, $communicationrecord->component);
$this->assertEquals(processor::PROVIDER_INACTIVE, $communicationrecord->active);
$this->assertEquals($communicationroomname, $communicationrecord->roomname);
$this->assertEquals($instancetype, $communicationrecord->instancetype);
// Test against the object.
$this->assertEquals($context->id, $communicationprocessor->get_context_id());
$this->assertEquals($context, $communicationprocessor->get_context());
$this->assertEquals($communicationprocessor->get_id(), $communicationrecord->id);
$this->assertEquals($communicationprocessor->is_instance_active(), $communicationrecord->active);
$this->assertEquals($communicationprocessor->get_room_name(), $communicationrecord->roomname);
}
/**
* Test delete instance.
*
* @covers ::delete_instance
* @covers ::create_instance
* @covers ::load_by_instance
*/
public function test_delete_instance(): void {
global $DB;
$this->resetAfterTest();
// Sameple test data.
$instanceid = 10;
$context = \core\context\system::instance();
$component = 'core';
$instancetype = 'mycommunication';
$selectedcommunication = 'communication_matrix';
$communicationroomname = 'communicationroom';
$communicationprocessor = processor::create_instance(
$context,
$selectedcommunication,
$instanceid,
$component,
$instancetype,
$communicationroomname,
);
$communicationprocessor->delete_instance();
// Now test the record against the database.
$communicationrecord = $DB->get_record('communication', [
'instanceid' => $instanceid,
'component' => $component,
'instancetype' => $instancetype,
]);
// Test against the set data.
$this->assertEmpty($communicationrecord);
// Test against the object.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: $component,
instancetype: $instancetype,
instanceid: $instanceid,
);
$this->assertNull($communicationprocessor);
}
/**
* Test load by id.
*
* @covers ::load_by_instance
* @covers ::get_room_provider
*/
public function test_load_by_instance(): void {
$this->resetAfterTest();
$course = $this->get_course();
$context = \core\context\course::instance($course->id);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertNotNull($communicationprocessor);
$this->assertInstanceOf(communication_provider::class, $communicationprocessor->get_room_provider());
$this->assertInstanceOf(room_chat_provider::class, $communicationprocessor->get_room_provider());
$this->assertInstanceOf(room_user_provider::class, $communicationprocessor->get_room_provider());
$this->assertInstanceOf(user_provider::class, $communicationprocessor->get_room_provider());
}
/**
* Test load by id.
*
* @covers ::load_by_id
* @covers ::get_room_provider
* @covers ::load_by_instance
*/
public function test_load_by_id(): void {
$this->resetAfterTest();
$course = $this->get_course();
$context = \core\context\course::instance($course->id);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$communicationprocessorbyid = processor::load_by_id($communicationprocessor->get_id());
$this->assertNotNull($communicationprocessorbyid);
$this->assertInstanceOf(communication_provider::class, $communicationprocessorbyid->get_room_provider());
$this->assertInstanceOf(room_chat_provider::class, $communicationprocessorbyid->get_room_provider());
$this->assertInstanceOf(room_user_provider::class, $communicationprocessorbyid->get_room_provider());
$this->assertInstanceOf(user_provider::class, $communicationprocessorbyid->get_room_provider());
}
/**
* Test get component.
*
* @covers ::get_component
* @covers ::load_by_instance
*/
public function test_get_component(): void {
$this->resetAfterTest();
$course = $this->get_course();
$context = \core\context\course::instance($course->id);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertEquals('core_course', $communicationprocessor->get_component());
}
/**
* Test get provider.
*
* @covers ::get_provider
* @covers ::load_by_instance
*/
public function test_get_provider(): void {
$this->resetAfterTest();
$course = $this->get_course();
$context = \core\context\course::instance($course->id);
// Test the communication record exists when fetching the active provider.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertEquals('communication_matrix', $communicationprocessor->get_provider());
// Test the communication record exists when specifying the provider.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
provider: 'communication_matrix',
);
$this->assertEquals('communication_matrix', $communicationprocessor->get_provider());
// Test the communication record exists when the provider is not active.
$communicationprocessor->update_instance(processor::PROVIDER_INACTIVE);
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
provider: 'communication_matrix',
);
$this->assertEquals('communication_matrix', $communicationprocessor->get_provider());
}
/**
* Test get room name.
*
* @covers ::get_room_name
* @covers ::load_by_instance
*/
public function test_get_room_name(): void {
$this->resetAfterTest();
$course = $this->get_course();
$context = \core\context\course::instance($course->id);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertEquals('Sampleroom', $communicationprocessor->get_room_name());
}
/**
* Test get room provider.
*
* @covers ::get_room_provider
* @covers ::require_room_features
* @covers ::supports_room_features
* @covers ::load_by_instance
*/
public function test_get_room_provider(): void {
$this->resetAfterTest();
$course = $this->get_course();
$context = \core\context\course::instance($course->id);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertInstanceOf(room_chat_provider::class, $communicationprocessor->get_room_provider());
}
/**
* Test get user provider.
*
* @covers ::get_user_provider
* @covers ::require_user_features
* @covers ::supports_user_features
* @covers ::load_by_instance
*/
public function test_get_user_provider(): void {
$this->resetAfterTest();
$course = $this->get_course();
$context = \core\context\course::instance($course->id);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertInstanceOf(user_provider::class, $communicationprocessor->get_room_provider());
}
/**
* Test get room user provider.
*
* @covers ::get_room_user_provider
* @covers ::require_room_features
* @covers ::require_room_user_features
* @covers ::supports_room_user_features
* @covers ::supports_room_features
* @covers ::load_by_instance
*/
public function test_get_room_user_provider(): void {
$this->resetAfterTest();
$course = $this->get_course();
$context = \core\context\course::instance($course->id);
// Test the communication record exists.
$communicationprocessor = processor::load_by_instance(
context: $context,
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertInstanceOf(room_user_provider::class, $communicationprocessor->get_room_user_provider());
}
/**
* Test get avatar.
*
* @covers ::get_avatar
* @covers ::load_by_instance
* @covers ::get_avatar_filename
* @covers ::set_avatar_filename
* @covers ::set_avatar_synced_flag
*/
public function test_get_avatar(): void {
$this->resetAfterTest();
$this->setAdminUser();
global $CFG;
$course = $this->get_course('Sampleroom', 'none');
// Sample data.
$communicationroomname = 'Sampleroom';
$selectedcommunication = 'communication_matrix';
$avatar = $this->create_communication_file(
'moodle_logo.jpg',
'moodle_logo.jpg',
);
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
provider: $selectedcommunication,
);
$communication->create_and_configure_room($communicationroomname, $avatar);
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$avatar = $communicationprocessor->get_avatar();
$this->assertNotNull($avatar);
$this->assertEquals($avatar->get_component(), 'core_communication');
$this->assertEquals($avatar->get_filearea(), 'avatar');
$this->assertEquals($avatar->get_itemid(), $communicationprocessor->get_id());
$this->assertEquals($avatar->get_filepath(), '/');
$this->assertEquals($avatar->get_filearea(), 'avatar');
$this->assertEquals($avatar->get_filename(), $communicationprocessor->get_avatar_filename());
// Change the avatar file name to something else and check it was set.
$communicationprocessor->set_avatar_filename('newname.svg');
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: 'core_course',
instancetype: 'coursecommunication',
instanceid: $course->id,
);
$this->assertEquals($communicationprocessor->get_avatar_filename(), 'newname.svg');
}
/**
* Test if the provider is enabled and configured, or disabled.
*
* @covers ::is_provider_available
*/
public function test_is_provider_available(): void {
$this->resetAfterTest();
$communicationprovider = 'communication_matrix';
$this->assertTrue(processor::is_provider_available($communicationprovider));
// Now test is disabling the plugin returns false.
set_config('disabled', 1, $communicationprovider);
$this->assertFalse(processor::is_provider_available($communicationprovider));
}
/**
* Test delete flagged user id's return correct users.
*
* @covers ::get_all_delete_flagged_userids
*/
public function test_get_all_delete_flagged_userids(): void {
$this->resetAfterTest();
$course = $this->get_course('Sampleroom', 'none');
$user1 = $this->getDataGenerator()->create_user()->id;
$user2 = $this->getDataGenerator()->create_user()->id;
// Sample data.
$communicationroomname = 'Sampleroom';
$selectedcommunication = 'communication_matrix';
$component = 'core_course';
$instancetype = 'coursecommunication';
// Load the communication api.
$communication = \core_communication\api::load_by_instance(
context: \core\context\course::instance($course->id),
component: $component,
instancetype: $instancetype,
instanceid: $course->id,
provider: $selectedcommunication,
);
$communication->create_and_configure_room($communicationroomname);
$communication->add_members_to_room([$user1, $user2]);
// Now remove user1 from the room.
$communication->remove_members_from_room([$user1]);
// Test against the object.
$communicationprocessor = processor::load_by_instance(
context: \core\context\course::instance($course->id),
component: $component,
instancetype: $instancetype,
instanceid: $course->id,
);
$this->assertEquals([$user1], $communicationprocessor->get_all_delete_flagged_userids());
}
}