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
@@ -0,0 +1,64 @@
<?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_chat\backup;
use core_external\external_api;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . "/phpunit/classes/restore_date_testcase.php");
/**
* Restore date tests.
*
* @package mod_chat
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_date_test extends \restore_date_testcase {
public function test_restore_dates(): void {
global $DB;
list($course, $chat) = $this->create_course_and_module('chat');
$result = \mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(\mod_chat_external::login_user_returns(), $result);
$chatsid = $result['chatsid'];
$result = \mod_chat_external::send_chat_message($chatsid, 'hello!');
$result = external_api::clean_returnvalue(\mod_chat_external::send_chat_message_returns(), $result);
$message = $DB->get_record('chat_messages', ['id' => $result['messageid']]);
$timestamp = 1000;
$DB->set_field('chat_messages', 'timestamp', $timestamp);
// Do backup and restore.
$newcourseid = $this->backup_and_restore($course);
$newchat = $DB->get_record('chat', ['course' => $newcourseid]);
$this->assertFieldsNotRolledForward($chat, $newchat, ['timemodified']);
$props = ['chattime'];
$this->assertFieldsRolledForward($chat, $newchat, $props);
$newmessages = $DB->get_records('chat_messages', ['chatid' => $newchat->id]);
foreach ($newmessages as $message) {
$this->assertEquals($timestamp, $message->timestamp);
}
}
}
+76
View File
@@ -0,0 +1,76 @@
<?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/>.
/**
* Steps definitions related to mod_chat.
*
* @package mod_chat
* @category test
* @copyright 2021 Dongsheng Cai
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../../lib/behat/behat_base.php');
/**
* Steps definitions related to mod_chat.
*
*/
class behat_mod_chat extends behat_base {
/**
* Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'.
*
* Recognised page names are:
* | pagetype | name meaning | description |
* | View | Chat name | The chat info page (view.php) |
*
* @param string $type identifies which type of page this is, e.g. 'View'.
* @param string $name chat instance name
* @return moodle_url the corresponding URL.
* @throws Exception with a meaningful error message if the specified page cannot be found.
*/
protected function resolve_page_instance_url(string $type, string $name): moodle_url {
switch (strtolower($type)) {
case 'view':
$cm = $this->get_cm_by_chat_name($name);
return new moodle_url('/mod/chat/view.php', ['id' => $cm->id]);
default:
throw new Exception('Unrecognised chat page type "' . $type . '."');
}
}
/**
* Get a chat by name.
*
* @param string $name chat name.
* @return stdClass the corresponding DB row.
*/
protected function get_chat_by_name(string $name): stdClass {
global $DB;
return $DB->get_record('chat', ['name' => $name], '*', MUST_EXIST);
}
/**
* Get a chat coursemodule object from the name.
*
* @param string $name chat name.
* @return stdClass cm from get_coursemodule_from_instance.
*/
protected function get_cm_by_chat_name(string $name): stdClass {
$chat = $this->get_chat_by_name($name);
return get_coursemodule_from_instance('chat', $chat->id, $chat->course);
}
}
@@ -0,0 +1,56 @@
@mod @mod_chat @core_completion
Feature: View activity completion information in the chat activity
In order to have visibility of chat completion requirements
As a student
I need to be able to view my chat completion progress
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Vinnie | Student1 | student1@example.com |
| teacher1 | Darrell | Teacher1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category | enablecompletion |
| Course 1 | C1 | 0 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| teacher1 | C1 | editingteacher |
And I enable "chat" "mod" plugin
Scenario: View automatic completion items
Given I log in as "teacher1"
And the following "activity" exists:
| activity | chat |
| course | C1 |
| name | Music history |
| section | 1 |
| completion | 2 |
| completionview | 1 |
And I am on "Course 1" course homepage
# Teacher view.
And I am on the "Music history" Activity page
And "Music history" should have the "View" completion condition
And I log out
# Student view.
And I am on the "Music history" Activity page logged in as student1
Then the "View" completion condition of "Music history" is displayed as "done"
@javascript
Scenario: Use manual completion
Given I log in as "teacher1"
And the following "activity" exists:
| activity | chat |
| course | C1 |
| name | Music history |
| section | 1 |
| completion | 1 |
And I am on "Course 1" course homepage
# Teacher view.
And "Music history" should have the "Mark as done" completion condition
And I log out
# Student view.
And I am on the "Music history" Activity page logged in as student1
Then the manual completion button of "Music history" is displayed as "Mark as done"
And I toggle the manual completion state of "Music history"
And the manual completion button of "Music history" is displayed as "Done"
@@ -0,0 +1,36 @@
@mod @mod_chat
Feature: Chat calendar entries
In order to notify students of upcoming chat sessons
As a teacher
I need to create a chat activity and publish the event times
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Tina | Teacher1 | teacher1@example.com |
| student1 | Sam | Student1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And I enable "chat" "mod" plugin
Scenario Outline: Create a chat activity with repeated chat times set
# Create an activity with repeated chat times
Given the following "activities" exist:
| activity | course | name | schedule |
| chat | C1 | Chat 1 | <scheduleset> |
And I log in as "teacher1"
# Confirm Chat activity visibility based on schedule
When I am viewing calendar in "upcoming" view
Then I <chatvisibility> see "Chat 1"
Examples:
| scheduleset | chatvisibility |
| 0 | should not |
| 1 | should |
| 2 | should |
| 3 | should |
@@ -0,0 +1,55 @@
@mod @mod_chat
Feature: Chat reset
In order to reuse past chat activities
As a teacher
I need to remove all previous data.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Tina | Teacher1 | teacher1@example.com |
| student1 | Sam | Student1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And I enable "chat" "mod" plugin
And the following "activities" exist:
| activity | name | Description | course | idnumber |
| chat | Test chat name | Test chat description | C1 | chat1 |
Scenario: Use course reset to update chat start date
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| startdate[day] | 1 |
| startdate[month] | January |
| startdate[year] | 2020 |
And I press "Save and display"
And I follow "Test chat name"
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| chattime[day] | 1 |
| chattime[month] | January |
| chattime[year] | 2020 |
| chattime[hour] | 12 |
| chattime[minute] | 00 |
And I press "Save and display"
And I am on the "Course 1" "reset" page
And I set the following fields to these values:
| reset_start_date[enabled] | 1 |
| reset_start_date[day] | 1 |
| reset_start_date[month] | January |
| reset_start_date[year] | 2030 |
And I press "Reset course"
And I should see "Date changed" in the "Chats" "table_row"
And I press "Continue"
Then I am on "Course 1" course homepage
And I follow "Test chat name"
And I navigate to "Settings" in current page administration
And I expand all fieldsets
And the "chattime[year]" select box should contain "2030"
@@ -0,0 +1,61 @@
@mod @mod_chat
Feature: Chat with my group
In order to chat with my group
As a student
I want to be able to see or select by group in the Chat activity
Background:
And the following "courses" exist:
| fullname | shortname |
| Test Course 1 | C1 |
And the following "groups" exist:
| name | course | idnumber | participation |
| Group 1 | C1 | G1 | 1 |
| Group 2 | C1 | G2 | 1 |
| Group 3 | C1 | G3 | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | TeacherG1 | 1 | teacher1@example.com |
| user1 | User1G1 | 1 | user1@example.com |
| user2 | User2G2 | 2 | user2@example.com |
| user3 | User3None | 3 | user3@example.com |
| user4 | User4NPgroup | 4 | user4@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| user1 | C1 | student |
| user2 | C1 | student |
| user3 | C1 | student |
| user4 | C1 | student |
And the following "group members" exist:
| user | group |
| teacher1 | G1 |
| user1 | G1 |
| user2 | G2 |
| user4 | G3 |
And I enable "chat" "mod" plugin
And the following "activities" exist:
| activity | name | intro | course | idnumber | groupmode |
| chat | Separate Chat | Chat with separate groups | C1 | chat1 | 1 |
| chat | Visible Chat | Chat with visible groups | C1 | chat2 | 2 |
Scenario Outline: Users should see their own participation groups in "separate groups" mode, and all
participation groups in "visible groups" mode.
Given I am on the "<chat>" "chat activity" page logged in as "<user>"
Then I <all> "All participants"
And I <G1> "Group 1"
And I <G2> "Group 2"
And I should not see "Group 3"
Examples:
| chat | user | all | G1 | G2 |
| chat1 | teacher1 | should see | should see | should see |
| chat1 | user1 | should not see | should see | should not see |
| chat1 | user2 | should not see | should not see | should see |
| chat1 | user3 | should see | should not see | should not see |
| chat1 | user4 | should see | should not see | should not see |
| chat2 | teacher1 | should see | should see | should see |
| chat2 | user1 | should see | should see | should see |
| chat2 | user2 | should see | should see | should see |
| chat2 | user3 | should see | should see | should see |
| chat2 | user4 | should see | should see | should see |
@@ -0,0 +1,49 @@
@mod @mod_chat
Feature: Chat with no calendar capabilites
In order to allow work effectively
As a teacher
I need to be able to create chats even when I cannot edit calendar events
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And I enable "chat" "mod" plugin
And the following "activity" exists:
| activity | chat |
| course | C1 |
| idnumber | 0001 |
| name | Test chat name |
| intro | Test chat description |
| section | 1 |
And I log in as "admin"
And I am on the "Course 1" "permissions" page
And I override the system permissions of "Teacher" role with:
| capability | permission |
| moodle/calendar:manageentries | Prohibit |
And I am on "Course 1" course homepage
And I follow "Test chat name"
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Repeat/publish session times | No repeats - publish the specified time only |
| id_chattime_day | 1 |
| id_chattime_month | 1 |
| id_chattime_year | 2017 |
And I press "Save and return to course"
And I log out
Scenario: Editing a chat
When I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I follow "Test chat name"
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| id_chattime_year | 2018 |
And I press "Save and return to course"
Then I should see "Test chat name"
@@ -0,0 +1,48 @@
@mod @mod_chat @javascript
Feature: View past chat sessions
In order for students to view past chat sessions
As a teacher
I need to be able to change the mod/chat:readlog permission for students
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | One | teacher1@example.com |
| student1 | Student | One | student1@example.com |
And the following "course" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And I enable "chat" "mod" plugin
Scenario Outline: View past chat sessions
# Display or hide past chat session based on example data
Given the following "activities" exist:
| activity | course | name | studentlogs |
| chat | C1 | Chat 1 | <studentlogvalue> |
And I am on the "Chat 1" "chat activity" page logged in as teacher1
# Display or hide past chat session by default based on mod/chat:readlog setting
And the following "role capability" exists:
| role | student |
| mod/chat:readlog | <readpermission> |
# Enter chat activity to create a session
And I click on "Enter the chat" "link"
# Close chat window
When I close all opened windows
And I reload the page
# Confirm that past chat sessions is always visible for teacher
Then I should see "Past sessions"
# Confirm past chat sessions visibility for student based on settings
And I am on the "Chat 1" "chat activity" page logged in as student1
And I <sessionvisibility> see "Past sessions"
# Regardless of studentlogvalue value if readpermission is allowed, then Past sessions will be visible for students
Examples:
| studentlogvalue | readpermission | sessionvisibility |
| 0 | allow | should |
| 1 | allow | should |
| 0 | prohibit | should not |
| 1 | prohibit | should |
+137
View File
@@ -0,0 +1,137 @@
<?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/>.
declare(strict_types=1);
namespace mod_chat;
use advanced_testcase;
use cm_info;
use core\activity_dates;
/**
* Class for unit testing mod_chat\dates.
*
* @package mod_chat
* @category test
* @copyright 2021 Dongsheng Cai
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class dates_test extends advanced_testcase {
/**
* Setup testcase.
*/
public function setUp(): void {
// Chat module is disabled by default, enable it for testing.
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
$manager::enable_plugin('chat', 1);
}
/**
* Data provider for get_dates_for_module().
* @return array[]
*/
public static function get_dates_for_module_provider(): array {
global $CFG;
require_once($CFG->dirroot . '/mod/chat/lib.php');
$now = time();
$past = $now - DAYSECS;
$future = $now + DAYSECS;
$dailynextchattime = $past + 2 * DAYSECS;
$weeklynextchattime = $past + 7 * DAYSECS;
$label = get_string('nextchattime', 'mod_chat');
return [
'chattime in the past (no schedule)' => [
$past, CHAT_SCHEDULE_NONE, []
],
'chattime in the past (single schedule)' => [
$past, CHAT_SCHEDULE_SINGLE, []
],
'chattime in the future' => [
$future, CHAT_SCHEDULE_SINGLE, [
[
'label' => $label,
'timestamp' => $future,
'dataid' => 'chattime',
],
]
],
'future chattime weekly' => [
$future, CHAT_SCHEDULE_WEEKLY, [
[
'label' => $label,
'timestamp' => $future,
'dataid' => 'chattime',
]
]
],
'future chattime daily' => [
$future, CHAT_SCHEDULE_DAILY, [
[
'label' => $label,
'timestamp' => $future,
'dataid' => 'chattime',
]
]
],
'past chattime daily' => [
$past, CHAT_SCHEDULE_DAILY, [
[
'label' => $label,
'timestamp' => $dailynextchattime,
'dataid' => 'chattime',
],
]
],
'past chattime weekly' => [
$past, CHAT_SCHEDULE_WEEKLY, [
[
'label' => $label,
'timestamp' => $weeklynextchattime,
'dataid' => 'chattime',
],
]
],
];
}
/**
* Test for get_dates_for_module().
*
* @dataProvider get_dates_for_module_provider
* @param int|null $chattime
* @param int|null $schedule
* @param array $expected The expected value of calling get_dates_for_module()
*/
public function test_get_dates_for_module(?int $chattime, ?int $schedule, array $expected): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$user = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user->id, $course->id);
$chat = ['course' => $course->id];
$chat['chattime'] = $chattime;
$chat['schedule'] = $schedule;
$modchat = $this->getDataGenerator()->create_module('chat', $chat);
$this->setUser($user);
$cm = get_coursemodule_from_instance('chat', $modchat->id);
$cminfo = cm_info::create($cm);
$dates = activity_dates::get_dates_for_module($cminfo, (int) $user->id);
$this->assertEquals($expected, $dates);
}
}
+184
View File
@@ -0,0 +1,184 @@
<?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/>.
/**
* Events tests.
*
* @package mod_chat
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_chat\event;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/chat/lib.php');
/**
* Events tests class.
*
* @package mod_chat
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class events_test extends \advanced_testcase {
/**
* Setup testcase.
*/
public function setUp(): void {
// Chat module is disabled by default, enable it for testing.
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
$manager::enable_plugin('chat', 1);
}
public function test_message_sent(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$cm = $DB->get_record('course_modules', array('id' => $chat->cmid));
// Logging in first user to the chat.
$this->setUser($user1->id);
$sid1 = chat_login_user($chat->id, 'ajax', 0, $course);
// Logging in second user to the chat.
$this->setUser($user2->id);
$sid2 = chat_login_user($chat->id, 'ajax', 0, $course);
// Getting the chatuser record.
$chatuser1 = $DB->get_record('chat_users', array('sid' => $sid1));
$chatuser2 = $DB->get_record('chat_users', array('sid' => $sid2));
$sink = $this->redirectEvents();
// Send a messaging from the first user. We pass the CM to chat_send_chatmessage() this time.
// This ensures that the event triggered when sending a message is filled with the correct information.
$this->setUser($user1->id);
$messageid = chat_send_chatmessage($chatuser1, 'Hello!', false, $cm);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
$this->assertInstanceOf('\mod_chat\event\message_sent', $event);
$this->assertEquals($messageid, $event->objectid);
$this->assertEquals($user1->id, $event->relateduserid);
$this->assertEquals($user1->id, $event->userid);
// Send a messaging from the first user. We DO NOT pass the CM to chat_send_chatmessage() this time.
// This ensures that the event triggered when sending a message is filled with the correct information.
$sink->clear();
$this->setUser($user2->id);
$messageid = chat_send_chatmessage($chatuser2, 'Hello!');
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
$this->assertInstanceOf('\mod_chat\event\message_sent', $event);
$this->assertEquals($messageid, $event->objectid);
$this->assertEquals($user2->id, $event->relateduserid);
$this->assertEquals($user2->id, $event->userid);
// Sending a message from the system should not trigger any event.
$sink->clear();
$this->setAdminUser();
chat_send_chatmessage($chatuser1, 'enter', true);
$this->assertEquals(0, $sink->count());
$sink->close();
}
public function test_sessions_viewed(): void {
global $USER;
$this->resetAfterTest();
// Not much can be tested here as the event is only triggered on a page load,
// let's just check that the event contains the expected basic information.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$params = array(
'context' => \context_module::instance($chat->cmid),
'objectid' => $chat->id,
'other' => array(
'start' => 1234,
'end' => 5678
)
);
$event = \mod_chat\event\sessions_viewed::create($params);
$event->add_record_snapshot('chat', $chat);
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\mod_chat\event\sessions_viewed', $event);
$this->assertEquals($USER->id, $event->userid);
$this->assertEquals(\context_module::instance($chat->cmid), $event->get_context());
$this->assertEquals(1234, $event->other['start']);
$this->assertEquals(5678, $event->other['end']);
$this->assertEquals($chat->id, $event->objectid);
$this->assertEquals($chat, $event->get_record_snapshot('chat', $chat->id));
}
public function test_course_module_instance_list_viewed(): void {
global $USER;
$this->resetAfterTest();
// Not much can be tested here as the event is only triggered on a page load,
// let's just check that the event contains the expected basic information.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$params = array(
'context' => \context_course::instance($course->id)
);
$event = \mod_chat\event\course_module_instance_list_viewed::create($params);
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\mod_chat\event\course_module_instance_list_viewed', $event);
$this->assertEquals($USER->id, $event->userid);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
}
public function test_course_module_viewed(): void {
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$cm = get_coursemodule_from_instance('chat', $chat->id);
$context = \context_module::instance($cm->id);
$params = array(
'objectid' => $chat->id,
'context' => $context
);
$event = \mod_chat\event\course_module_viewed::create($params);
$event->add_record_snapshot('chat', $chat);
$event->trigger();
$url = new \moodle_url('/mod/chat/view.php', array('id' => $cm->id));
$this->assertEquals($url, $event->get_url());
$event->get_name();
}
}
+139
View File
@@ -0,0 +1,139 @@
<?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/>.
/**
* Tests for external function mod_chat_view_sessions.
*
* @package mod_chat
* @category external
* @copyright 2022 Rodrigo Mady <rodrigo.mady@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 4.3
*/
namespace mod_chat\external;
use externallib_advanced_testcase;
use moodle_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* Test Class for external function mod_chat_view_sessions.
*
* @package mod_chat
* @category external
* @copyright 2023 Rodrigo Mady <rodrigo.mady@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 4.3
* @coversDefaultClass \mod_chat\external\view_sessions
*/
class view_sessions_test extends externallib_advanced_testcase {
/**
* Prepare the test.
*
* @return array
*/
private function prepare_test_data(): array {
global $DB;
$this->resetAfterTest(true);
// Chat module is disabled by default, enable it for testing.
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
$manager::enable_plugin('chat', 1);
$course = $this->getDataGenerator()->create_course();
$student1 = $this->getDataGenerator()->create_and_enrol($course);
$chat = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
$context = \context_module::instance($chat->cmid);
$studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student']);
assign_capability('mod/chat:readlog', CAP_ALLOW, $studentroleid, $context, true);
$this->setUser($student1);
return [
'chat' => $chat,
];
}
/**
* Helper to call view_sessions WS function.
*
* @param int $cmid
* @param int $sessionstart
* @param int $sessionend
* @return array
*/
protected function view_sessions(int $cmid, int $sessionstart = 0, int $sessionend = 0): array {
$result = view_sessions::execute($cmid, $sessionstart, $sessionend);
return \core_external\external_api::clean_returnvalue(view_sessions::execute_returns(), $result);
}
/**
* Test for webservice view sessions.
* @covers ::execute
*/
public function test_view_sessions(): void {
$data = $this->prepare_test_data();
$result = $this->view_sessions($data['chat']->cmid);
$this->assertArrayHasKey('status', $result);
$this->assertArrayHasKey('warnings', $result);
$this->assertTrue($result['status']);
}
/**
* Test for webservice view sessions without capability.
* @covers ::execute
*/
public function test_view_sessions_without_capability(): void {
global $DB;
$data = $this->prepare_test_data();
$context = \context_module::instance($data['chat']->cmid);
$studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student']);
assign_capability('mod/chat:readlog', CAP_PROHIBIT, $studentroleid, $context, true);
$result = $this->view_sessions($data['chat']->cmid);
$this->assertArrayHasKey('status', $result);
$this->assertArrayHasKey('warnings', $result);
$this->assertFalse($result['status']);
$this->assertEquals(get_string('nopermissiontoseethechatlog', 'chat'), $result['warnings'][0]['message']);
}
/**
* Test for webservice view sessions with start and end dates.
* @covers ::execute
*/
public function test_view_sessions_with_start_end_dates(): void {
$data = $this->prepare_test_data();
$result = $this->view_sessions($data['chat']->cmid, strtotime('today'), strtotime('tomorrow'));
$this->assertArrayHasKey('status', $result);
$this->assertArrayHasKey('warnings', $result);
$this->assertTrue($result['status']);
}
/**
* Test execute with no valid instance of cmid.
* @covers ::execute
*/
public function test_view_sessions_no_instance(): void {
$this->expectException(moodle_exception::class);
$this->view_sessions(1234);
}
}
+501
View File
@@ -0,0 +1,501 @@
<?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_chat;
use core_external\external_api;
use externallib_advanced_testcase;
use mod_chat_external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* External mod_chat functions unit tests
*
* @package mod_chat
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
class externallib_test extends externallib_advanced_testcase {
/**
* Setup testcase.
*/
public function setUp(): void {
// Chat module is disabled by default, enable it for testing.
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
$manager::enable_plugin('chat', 1);
}
/**
* Test login user
*/
public function test_login_user(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$user = self::getDataGenerator()->create_user();
$this->setUser($user);
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
// Test session started.
$sid = $DB->get_field('chat_users', 'sid', array('userid' => $user->id, 'chatid' => $chat->id));
$this->assertEquals($result['chatsid'], $sid);
}
/**
* Test get chat users
*/
public function test_get_chat_users(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$user1 = self::getDataGenerator()->create_user();
$user2 = self::getDataGenerator()->create_user();
$this->setUser($user1);
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user1->id, $course->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user2->id, $course->id, $studentrole->id);
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
$this->setUser($user2);
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
// Get users.
$result = mod_chat_external::get_chat_users($result['chatsid']);
$result = external_api::clean_returnvalue(mod_chat_external::get_chat_users_returns(), $result);
// Check correct users.
$this->assertCount(2, $result['users']);
$found = 0;
foreach ($result['users'] as $user) {
if ($user['id'] == $user1->id or $user['id'] == $user2->id) {
$found++;
}
}
$this->assertEquals(2, $found);
}
/**
* Test send and get chat messages
*/
public function test_send_get_chat_message(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$user = self::getDataGenerator()->create_user();
$this->setUser($user);
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
$chatsid = $result['chatsid'];
$result = mod_chat_external::send_chat_message($chatsid, 'hello!');
$result = external_api::clean_returnvalue(mod_chat_external::send_chat_message_returns(), $result);
// Test messages received.
$result = mod_chat_external::get_chat_latest_messages($chatsid, 0);
$result = external_api::clean_returnvalue(mod_chat_external::get_chat_latest_messages_returns(), $result);
foreach ($result['messages'] as $message) {
// Ommit system messages, like user just joined in.
if ($message['system']) {
continue;
}
$this->assertEquals('hello!', $message['message']);
}
}
/**
* Test view_chat
*/
public function test_view_chat(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$context = \context_module::instance($chat->cmid);
$cm = get_coursemodule_from_instance('chat', $chat->id);
// Test invalid instance id.
try {
mod_chat_external::view_chat(0);
$this->fail('Exception expected due to invalid mod_chat instance id.');
} catch (\moodle_exception $e) {
$this->assertEquals('invalidrecord', $e->errorcode);
}
// Test not-enrolled user.
$user = self::getDataGenerator()->create_user();
$this->setUser($user);
try {
mod_chat_external::view_chat($chat->id);
$this->fail('Exception expected due to not enrolled user.');
} catch (\moodle_exception $e) {
$this->assertEquals('requireloginerror', $e->errorcode);
}
// Test user with full capabilities.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$result = mod_chat_external::view_chat($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::view_chat_returns(), $result);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = array_shift($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_chat\event\course_module_viewed', $event);
$this->assertEquals($context, $event->get_context());
$moodlechat = new \moodle_url('/mod/chat/view.php', array('id' => $cm->id));
$this->assertEquals($moodlechat, $event->get_url());
$this->assertEventContextNotUsed($event);
$this->assertNotEmpty($event->get_name());
// Test user with no capabilities.
// We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
assign_capability('mod/chat:chat', CAP_PROHIBIT, $studentrole->id, $context->id);
accesslib_clear_all_caches_for_unit_testing();
try {
mod_chat_external::view_chat($chat->id);
$this->fail('Exception expected due to missing capability.');
} catch (\moodle_exception $e) {
$this->assertEquals('nopermissions', $e->errorcode);
}
}
/**
* Test get_chats_by_courses
*/
public function test_get_chats_by_courses(): void {
global $DB, $CFG;
$this->resetAfterTest(true);
$this->setAdminUser();
// Set global chat method.
$CFG->chat_method = 'header_js';
$course1 = self::getDataGenerator()->create_course();
$chatoptions1 = array(
'course' => $course1->id,
'name' => 'First Chat'
);
$chat1 = self::getDataGenerator()->create_module('chat', $chatoptions1);
$course2 = self::getDataGenerator()->create_course();
$chatoptions2 = array(
'course' => $course2->id,
'name' => 'Second Chat'
);
$chat2 = self::getDataGenerator()->create_module('chat', $chatoptions2);
$student1 = $this->getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
// Enroll Student1 in Course1.
self::getDataGenerator()->enrol_user($student1->id, $course1->id, $studentrole->id);
$this->setUser($student1);
$chats = mod_chat_external::get_chats_by_courses();
// We need to execute the return values cleaning process to simulate the web service server.
$chats = external_api::clean_returnvalue(mod_chat_external::get_chats_by_courses_returns(), $chats);
$this->assertCount(1, $chats['chats']);
$this->assertEquals('First Chat', $chats['chats'][0]['name']);
// We see 12 fields.
$this->assertCount(13, $chats['chats'][0]);
// As Student you cannot see some chat properties like 'section'.
$this->assertFalse(isset($chats['chats'][0]['section']));
// Student1 is not enrolled in course2. The webservice will return a warning!
$chats = mod_chat_external::get_chats_by_courses(array($course2->id));
// We need to execute the return values cleaning process to simulate the web service server.
$chats = external_api::clean_returnvalue(mod_chat_external::get_chats_by_courses_returns(), $chats);
$this->assertCount(0, $chats['chats']);
$this->assertEquals(1, $chats['warnings'][0]['warningcode']);
// Now as admin.
$this->setAdminUser();
// As Admin we can see this chat.
$chats = mod_chat_external::get_chats_by_courses(array($course2->id));
// We need to execute the return values cleaning process to simulate the web service server.
$chats = external_api::clean_returnvalue(mod_chat_external::get_chats_by_courses_returns(), $chats);
$this->assertCount(1, $chats['chats']);
$this->assertEquals('Second Chat', $chats['chats'][0]['name']);
$this->assertEquals('header_js', $chats['chats'][0]['chatmethod']);
// We see 17 fields.
$this->assertCount(18, $chats['chats'][0]);
// As an Admin you can see some chat properties like 'section'.
$this->assertEquals(0, $chats['chats'][0]['section']);
// Enrol student in the second course.
self::getDataGenerator()->enrol_user($student1->id, $course2->id, $studentrole->id);
$this->setUser($student1);
$chats = mod_chat_external::get_chats_by_courses();
$chats = external_api::clean_returnvalue(mod_chat_external::get_chats_by_courses_returns(), $chats);
$this->assertCount(2, $chats['chats']);
}
/**
* Test get_sessions_empty_chat
*/
public function test_get_sessions_empty_chat(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$result = mod_chat_external::get_sessions($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::get_sessions_returns(), $result);
$this->assertEmpty($result['sessions']);
$this->assertEmpty($result['warnings']);
}
/**
* Test get_sessions_no_permissions_for_student
*/
public function test_get_sessions_no_permissions_for_student(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
// Disable logs for students.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id, 'studentlogs' => 0));
// The admin has permissions to check logs.
$result = mod_chat_external::get_sessions($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::get_sessions_returns(), $result);
$this->assertEmpty($result['sessions']);
$this->assertEmpty($result['warnings']);
$user = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
unassign_capability('mod/chat:readlog', $studentrole->id);
accesslib_clear_all_caches_for_unit_testing();
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
$this->setUser($user);
// Students don't have permissions.
$this->expectException('moodle_exception');
mod_chat_external::get_sessions($chat->id);
}
/**
* Test get_sessions_not_completed_session
*/
public function test_get_sessions_not_completed_session(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$user = self::getDataGenerator()->create_user();
$this->setUser($user);
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
// Start a chat and send just one message.
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
$chatsid = $result['chatsid'];
$result = mod_chat_external::send_chat_message($chatsid, 'hello!');
$result = external_api::clean_returnvalue(mod_chat_external::send_chat_message_returns(), $result);
// Check session is not marked as completed so it is not returned.
$result = mod_chat_external::get_sessions($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::get_sessions_returns(), $result);
$this->assertEmpty($result['sessions']);
$this->assertEmpty($result['warnings']);
// Pass showall parameter to indicate that we want not completed sessions.
$result = mod_chat_external::get_sessions($chat->id, 0, true);
$result = external_api::clean_returnvalue(mod_chat_external::get_sessions_returns(), $result);
$this->assertCount(1, $result['sessions']); // One session.
$this->assertFalse($result['sessions'][0]['iscomplete']); // Session not complete.
$this->assertEmpty($result['warnings']);
}
/**
* Test get_sessions_completed_session
*/
public function test_get_sessions_completed_session(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$user1 = self::getDataGenerator()->create_user();
$user2 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user1->id, $course->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user2->id, $course->id, $studentrole->id);
// Start a chat and completeit.
$this->setUser($user1);
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
$chatsid = $result['chatsid'];
$result = mod_chat_external::send_chat_message($chatsid, 'hello!');
$result = external_api::clean_returnvalue(mod_chat_external::send_chat_message_returns(), $result);
$this->setUser($user2);
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
$chatsid = $result['chatsid'];
$result = mod_chat_external::send_chat_message($chatsid, 'hello to you!');
$result = external_api::clean_returnvalue(mod_chat_external::send_chat_message_returns(), $result);
// Need to change first messages and last message times to mark the session completed.
// We receive 4 messages (2 system messages that indicates user joined and the 2 messages sent by the users).
$messages = $DB->get_records('chat_messages', array('chatid' => $chat->id));
// Messages just one hour ago and 70 seconds between them.
$timegap = 0;
$timenow = time();
foreach ($messages as $message) {
$DB->set_field('chat_messages', 'timestamp', $timenow - HOURSECS + $timegap, array('id' => $message->id));
$timegap += 70;
}
// Check session is completed.
$result = mod_chat_external::get_sessions($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::get_sessions_returns(), $result);
$this->assertCount(1, $result['sessions']); // One session.
$this->assertTrue($result['sessions'][0]['iscomplete']); // Session complete.
// The session started when user1 entered the chat.
$this->assertEquals($timenow - HOURSECS, $result['sessions'][0]['sessionstart']);
$this->assertEmpty($result['warnings']);
}
/**
* Test get_session_messages
*/
public function test_get_session_messages(): void {
global $DB;
$this->resetAfterTest(true);
// Setup test data.
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$user1 = self::getDataGenerator()->create_user();
$user2 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user1->id, $course->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user2->id, $course->id, $studentrole->id);
// Start a chat and send a few messages.
$this->setUser($user1);
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
$chatsid = $result['chatsid'];
mod_chat_external::send_chat_message($chatsid, 'hello!');
mod_chat_external::send_chat_message($chatsid, 'bye bye!');
$this->setUser($user2);
$result = mod_chat_external::login_user($chat->id);
$result = external_api::clean_returnvalue(mod_chat_external::login_user_returns(), $result);
$chatsid = $result['chatsid'];
mod_chat_external::send_chat_message($chatsid, 'greetings!');
// Pass showall parameter to indicate that we want not completed sessions.
$result = mod_chat_external::get_sessions($chat->id, 0, true);
$result = external_api::clean_returnvalue(mod_chat_external::get_sessions_returns(), $result);
$this->assertCount(1, $result['sessions']); // One session.
$sessionstart = $result['sessions'][0]['sessionstart'];
$sessionend = $result['sessions'][0]['sessionend'];
$result = mod_chat_external::get_session_messages($chat->id, $sessionstart, $sessionend);
$result = external_api::clean_returnvalue(mod_chat_external::get_session_messages_returns(), $result);
$this->assertCount(5, $result['messages']); // 2 system + 3 personal messages.
$found = 0;
foreach ($result['messages'] as $message) {
if (!$message['issystem']) {
if ($message['userid'] == $user1->id) {
if ($message['message'] != 'hello!') {
$this->assertEquals('bye bye!', $message['message']);
$found++;
}
} else {
$this->assertEquals($user2->id, $message['userid']);
$this->assertEquals('greetings!', $message['message']);
$found++;
}
}
}
$this->assertEquals(2, $found);
}
}
+163
View File
@@ -0,0 +1,163 @@
<?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_chat;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/chat/lib.php');
/**
* Tests for format_message.
*
* @package mod_chat
* @copyright 2016 Andrew NIcols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class format_message_test extends \advanced_testcase {
const USER_CURRENT = 1;
const USER_OTHER = 2;
public function chat_format_message_manually_provider() {
$dateregexp = '\d{2}:\d{2}';
return [
'Beep everyone' => [
'message' => 'beep all',
'issystem' => false,
'willreturn' => true,
'expecttext' => "/^{$dateregexp}: " . get_string('messagebeepseveryone', 'chat', '__CURRENTUSER__') . ': /',
'refreshusers' => false,
'beep' => true,
],
'Beep the current user' => [
'message' => 'beep __CURRENTUSER__',
'issystem' => false,
'willreturn' => true,
'expecttext' => "/^{$dateregexp}: " . get_string('messagebeepsyou', 'chat', '__CURRENTUSER__') . ': /',
'refreshusers' => false,
'beep' => true,
],
'Beep another user' => [
'message' => 'beep __OTHERUSER__',
'issystem' => false,
'willreturn' => false,
'expecttext' => null,
'refreshusers' => null,
'beep' => null,
],
'Malformed beep' => [
'message' => 'beep',
'issystem' => false,
'willreturn' => true,
'expecttext' => "/^{$dateregexp} __CURRENTUSER_FIRST__: beep$/",
'refreshusers' => false,
'beep' => false,
],
'/me says' => [
'message' => '/me writes a test',
'issystem' => false,
'willreturn' => true,
'expecttext' => "/^{$dateregexp}: \*\*\* __CURRENTUSER_FIRST__ writes a test$/",
'refreshusers' => false,
'beep' => false,
],
'Invalid command' => [
'message' => '/help',
'issystem' => false,
'willreturn' => true,
'expecttext' => "/^{$dateregexp} __CURRENTUSER_FIRST__: \/help$/",
'refreshusers' => false,
'beep' => false,
],
'To user' => [
'message' => 'To Bernard:I love tests',
'issystem' => false,
'willreturn' => true,
'expecttext' => "/^{$dateregexp}: __CURRENTUSER_FIRST__ " . get_string('saidto', 'chat') . " Bernard: I love tests$/",
'refreshusers' => false,
'beep' => false,
],
'To user trimmed' => [
'message' => 'To Bernard: I love tests',
'issystem' => false,
'willreturn' => true,
'expecttext' => "/^{$dateregexp}: __CURRENTUSER_FIRST__ " . get_string('saidto', 'chat') . " Bernard: I love tests$/",
'refreshusers' => false,
'beep' => false,
],
'System: enter' => [
'message' => 'enter',
'issystem' => true,
'willreturn' => true,
'expecttext' => "/^{$dateregexp}: " . get_string('messageenter', 'chat', '__CURRENTUSER__') . "$/",
'refreshusers' => true,
'beep' => false,
],
'System: exit' => [
'message' => 'exit',
'issystem' => true,
'willreturn' => true,
'expecttext' => "/^{$dateregexp}: " . get_string('messageexit', 'chat', '__CURRENTUSER__') . "$/",
'refreshusers' => true,
'beep' => false,
],
];
}
/**
* @dataProvider chat_format_message_manually_provider
*/
public function test_chat_format_message_manually($messagetext, $issystem, $willreturn,
$expecttext, $refreshusers, $expectbeep): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$currentuser = $this->getDataGenerator()->create_user();
$this->setUser($currentuser);
$otheruser = $this->getDataGenerator()->create_user();
// Replace the message texts.
// These can't be done in the provider because it runs before the
// test starts.
$messagetext = str_replace('__CURRENTUSER__', $currentuser->id, $messagetext);
$messagetext = str_replace('__OTHERUSER__', $otheruser->id, $messagetext);
$message = (object) [
'message' => $messagetext,
'timestamp' => time(),
'issystem' => $issystem,
];
$result = chat_format_message_manually($message, $course->id, $currentuser, $currentuser);
if (!$willreturn) {
$this->assertFalse($result);
} else {
$this->assertNotFalse($result);
if (!empty($expecttext)) {
$expecttext = str_replace('__CURRENTUSER__', fullname($currentuser), $expecttext);
$expecttext = str_replace('__CURRENTUSER_FIRST__', $currentuser->firstname, $expecttext);
$this->assertMatchesRegularExpression($expecttext, $result->text);
}
$this->assertEquals($refreshusers, $result->refreshusers);
$this->assertEquals($expectbeep, $result->beep);
}
}
}
+75
View File
@@ -0,0 +1,75 @@
<?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/>.
/**
* mod_chat data generator.
*
* @package core
* @category test
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* mod_chat data generator class.
*
* @package core
* @category test
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_chat_generator extends testing_module_generator {
/**
* @var int keep track of how many messages have been created.
*/
protected $messagecount = 0;
/**
* To be called from data reset code only,
* do not use in tests.
* @return void
*/
public function reset() {
$this->messagecount = 0;
parent::reset();
}
public function create_instance($record = null, array $options = null) {
$record = (object)(array)$record;
if (!isset($record->keepdays)) {
$record->keepdays = 0;
}
if (!isset($record->studentlogs)) {
$record->studentlogs = 0;
}
if (!isset($record->chattime)) {
$record->chattime = time() - 2;
}
if (!isset($record->schedule)) {
$record->schedule = 0;
}
if (!isset($record->timemodified)) {
$record->timemodified = time();
}
return parent::create_instance($record, (array)$options);
}
}
+56
View File
@@ -0,0 +1,56 @@
<?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_chat;
/**
* Generator tests class.
*
* @package mod_chat
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class generator_test extends \advanced_testcase {
/**
* Setup testcase.
*/
public function setUp(): void {
// Chat module is disabled by default, enable it for testing.
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
$manager::enable_plugin('chat', 1);
}
public function test_create_instance(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$this->assertFalse($DB->record_exists('chat', array('course' => $course->id)));
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id));
$this->assertEquals(1, $DB->count_records('chat', array('course' => $course->id)));
$this->assertTrue($DB->record_exists('chat', array('course' => $course->id)));
$this->assertTrue($DB->record_exists('chat', array('id' => $chat->id)));
$params = array('course' => $course->id, 'name' => 'One more chat');
$chat = $this->getDataGenerator()->create_module('chat', $params);
$this->assertEquals(2, $DB->count_records('chat', array('course' => $course->id)));
$this->assertEquals('One more chat', $DB->get_field_select('chat', 'name', 'id = :id', array('id' => $chat->id)));
}
}
+747
View File
@@ -0,0 +1,747 @@
<?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/>.
/**
* Contains class containing unit tests for mod/chat/lib.php.
*
* @package mod_chat
* @category test
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_chat;
defined('MOODLE_INTERNAL') || die();
/**
* Class containing unit tests for mod/chat/lib.php.
*
* @package mod_chat
* @category test
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class lib_test extends \advanced_testcase {
public function setUp(): void {
$this->resetAfterTest();
// Chat module is disabled by default, enable it for testing.
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
$manager::enable_plugin('chat', 1);
}
/*
* The chat's event should not be shown to a user when the user cannot view the chat at all.
*/
public function test_chat_core_calendar_provide_event_action_in_hidden_section(): void {
global $CFG;
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a student.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => usergetmidnight(time())));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Set sections 0 as hidden.
set_section_visible($course->id, 0, 0);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
// Confirm the event is not shown at all.
$this->assertNull($actionevent);
}
/*
* The chat's event should not be shown to a user who does not have permission to view the chat at all.
*/
public function test_chat_core_calendar_provide_event_action_for_non_user(): void {
global $CFG;
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => usergetmidnight(time())));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
// Confirm the event is not shown at all.
$this->assertNull($actionevent);
}
public function test_chat_core_calendar_provide_event_action_chattime_event_yesterday(): void {
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => time() - DAYSECS));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
// Confirm the event is not shown at all.
$this->assertNull($actionevent);
}
public function test_chat_core_calendar_provide_event_action_chattime_event_yesterday_for_user(): void {
global $CFG;
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Enrol a student in the course.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => time() - DAYSECS));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
// Confirm the event is not shown at all.
$this->assertNull($actionevent);
}
public function test_chat_core_calendar_provide_event_action_chattime_event_today(): void {
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => usergetmidnight(time())));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_chat_core_calendar_provide_event_action_chattime_event_today_for_user(): void {
global $CFG;
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Enrol a student in the course.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => usergetmidnight(time())));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_chat_core_calendar_provide_event_action_chattime_event_tonight(): void {
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => usergetmidnight(time()) + (23 * HOURSECS)));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_chat_core_calendar_provide_event_action_chattime_event_tonight_for_user(): void {
global $CFG;
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Enrol a student in the course.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => usergetmidnight(time()) + (23 * HOURSECS)));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_chat_core_calendar_provide_event_action_chattime_event_tomorrow(): void {
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => time() + DAYSECS));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertFalse($actionevent->is_actionable());
}
public function test_chat_core_calendar_provide_event_action_chattime_event_tomorrow_for_user(): void {
global $CFG;
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Enrol a student in the course.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create a chat.
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => time() + DAYSECS));
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertFalse($actionevent->is_actionable());
}
public function test_chat_core_calendar_provide_event_action_chattime_event_different_timezones(): void {
global $CFG;
$this->setAdminUser();
// Create a course.
$course = $this->getDataGenerator()->create_course();
$hour = gmdate('H');
// This could have been much easier if MDL-37327 were implemented.
// We don't know when this test is being ran and there is no standard way to
// mock the time() function (MDL-37327 to handle that).
if ($hour < 10) {
$timezone1 = 'UTC'; // GMT.
$timezone2 = 'Pacific/Pago_Pago'; // GMT -11:00.
} else if ($hour < 11) {
$timezone1 = 'Pacific/Kiritimati'; // GMT +14:00.
$timezone2 = 'America/Sao_Paulo'; // GMT -03:00.
} else {
$timezone1 = 'Pacific/Kiritimati'; // GMT +14:00.
$timezone2 = 'UTC'; // GMT.
}
$this->setTimezone($timezone2);
// Enrol 2 students with different timezones in the course.
$student1 = $this->getDataGenerator()->create_and_enrol($course, 'student', (object)['timezone' => $timezone1]);
$student2 = $this->getDataGenerator()->create_and_enrol($course, 'student', (object)['timezone' => $timezone2]);
// Create a chat.
$chat1 = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => mktime(1, 0, 0))); // This is always yesterday in timezone1 time
// and always today in timezone2 time.
// Create a chat.
$chat2 = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
'chattime' => mktime(1, 0, 0) + DAYSECS)); // This is always today in timezone1 time
// and always tomorrow in timezone2 time.
// Create calendar events for the 2 chats above.
$event1 = $this->create_action_event($course->id, $chat1->id, CHAT_EVENT_TYPE_CHATTIME);
$event2 = $this->create_action_event($course->id, $chat2->id, CHAT_EVENT_TYPE_CHATTIME);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for student1.
$actionevent11 = mod_chat_core_calendar_provide_event_action($event1, $factory, $student1->id);
$actionevent12 = mod_chat_core_calendar_provide_event_action($event1, $factory, $student2->id);
$actionevent21 = mod_chat_core_calendar_provide_event_action($event2, $factory, $student1->id);
$actionevent22 = mod_chat_core_calendar_provide_event_action($event2, $factory, $student2->id);
// Confirm event1 is not shown to student1 at all.
$this->assertNull($actionevent11, 'Failed for UTC time ' . gmdate('H:i'));
// Confirm event1 was decorated for student2 and it is actionable.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent12);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent12->get_name());
$this->assertInstanceOf('moodle_url', $actionevent12->get_url());
$this->assertEquals(1, $actionevent12->get_item_count());
$this->assertTrue($actionevent12->is_actionable());
// Confirm event2 was decorated for student1 and it is actionable.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent21);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent21->get_name());
$this->assertInstanceOf('moodle_url', $actionevent21->get_url());
$this->assertEquals(1, $actionevent21->get_item_count());
$this->assertTrue($actionevent21->is_actionable());
// Confirm event2 was decorated for student2 and it is not actionable.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent22);
$this->assertEquals(get_string('enterchat', 'chat'), $actionevent22->get_name());
$this->assertInstanceOf('moodle_url', $actionevent22->get_url());
$this->assertEquals(1, $actionevent22->get_item_count());
$this->assertFalse($actionevent22->is_actionable());
}
/**
* Test for chat_get_sessions().
*/
public function test_chat_get_sessions(): void {
global $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
// Setup test data.
$this->setAdminUser();
$course = $generator->create_course();
$chat = $generator->create_module('chat', ['course' => $course->id]);
$user1 = $generator->create_user();
$user2 = $generator->create_user();
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
$generator->enrol_user($user1->id, $course->id, $studentrole->id);
$generator->enrol_user($user2->id, $course->id, $studentrole->id);
// Login as user 1.
$this->setUser($user1);
$chatsid = chat_login_user($chat->id, 'ajax', 0, $course);
$chatuser = $DB->get_record('chat_users', ['sid' => $chatsid]);
// Get the messages for this chat session.
$messages = chat_get_session_messages($chat->id, false, 0, 0, 'timestamp DESC');
// We should have just 1 system (enter) messages.
$this->assertCount(1, $messages);
// This is when the session starts (when the first message - enter - has been sent).
$sessionstart = reset($messages)->timestamp;
// Send some messages.
chat_send_chatmessage($chatuser, 'hello!');
chat_send_chatmessage($chatuser, 'bye bye!');
// Login as user 2.
$this->setUser($user2);
$chatsid = chat_login_user($chat->id, 'ajax', 0, $course);
$chatuser = $DB->get_record('chat_users', ['sid' => $chatsid]);
// Send a message and take note of this message ID.
$messageid = chat_send_chatmessage($chatuser, 'greetings!');
// This is when the session ends (timestamp of the last message sent to the chat).
$sessionend = $DB->get_field('chat_messages', 'timestamp', ['id' => $messageid]);
// Get the messages for this chat session.
$messages = chat_get_session_messages($chat->id, false, 0, 0, 'timestamp DESC');
// We should have 3 user and 2 system (enter) messages.
$this->assertCount(5, $messages);
// Fetch the chat sessions from the messages we retrieved.
$sessions = chat_get_sessions($messages, true);
// There should be only one session.
$this->assertCount(1, $sessions);
// Get this session.
$session = reset($sessions);
// Confirm that the start and end times of the session matches.
$this->assertEquals($sessionstart, $session->sessionstart);
$this->assertEquals($sessionend, $session->sessionend);
// Confirm we have 2 participants in the chat.
$this->assertCount(2, $session->sessionusers);
}
/**
* Test for chat_get_sessions with messages belonging to multiple sessions.
*/
public function test_chat_get_sessions_multiple(): void {
$messages = [];
$gap = 5; // 5 secs.
$now = time();
$timestamp = $now;
// Messages belonging to 3 sessions. Session 1 has 10 messages, 2 has 15, 3 has 25.
$sessionusers = [];
$sessiontimes = [];
$session = 0; // Incomplete session.
for ($i = 1; $i <= 50; $i++) {
// Take note of expected session times as we go through.
switch ($i) {
case 1:
// Session 1 start time.
$sessiontimes[0]['start'] = $timestamp;
break;
case 10:
// Session 1 end time.
$sessiontimes[0]['end'] = $timestamp;
break;
case 11:
// Session 2 start time.
$sessiontimes[1]['start'] = $timestamp;
break;
case 25:
// Session 2 end time.
$sessiontimes[1]['end'] = $timestamp;
break;
case 26:
// Session 3 start time.
$sessiontimes[2]['start'] = $timestamp;
break;
case 50:
// Session 3 end time.
$sessiontimes[2]['end'] = $timestamp;
break;
}
// User 1 to 5.
$user = rand(1, 5);
// Let's also include system messages as well. Give them to pop in 1-in-10 chance.
$issystem = rand(1, 10) == 10;
if ($issystem) {
$message = 'enter';
} else {
$message = 'Message ' . $i;
if (!isset($sessionusers[$session][$user])) {
$sessionusers[$session][$user] = 1;
} else {
$sessionusers[$session][$user]++;
}
}
$messages[] = (object)[
'id' => $i,
'chatid' => 1,
'userid' => $user,
'message' => $message,
'issystem' => $issystem,
'timestamp' => $timestamp,
];
// Set the next timestamp.
if ($i == 10 || $i == 25) {
// New session.
$session++;
$timestamp += CHAT_SESSION_GAP + 1;
} else {
$timestamp += $gap;
}
}
// Reverse sort the messages so they're in descending order.
rsort($messages);
// Get chat sessions showing only complete ones.
$completesessions = chat_get_sessions($messages);
// Session 1 is incomplete, so there should only be 2 sessions when $showall is false.
$this->assertCount(2, $completesessions);
// Reverse sort sessions so they are in ascending order matching our expected session times and users.
$completesessions = array_reverse($completesessions);
foreach ($completesessions as $index => $session) {
// We increment index by 1 because the incomplete expected session (index=0) is not included.
$expectedindex = $index + 1;
// Check the session users.
$users = $sessionusers[$expectedindex];
$this->assertCount(count($users), $session->sessionusers);
// Check the message counts for each user in this session.
foreach ($users as $userid => $messagecount) {
$this->assertEquals($messagecount, $session->sessionusers[$userid]);
}
$sessionstart = $sessiontimes[$expectedindex]['start'];
$sessionend = $sessiontimes[$expectedindex]['end'];
$this->assertEquals($sessionstart, $session->sessionstart);
$this->assertEquals($sessionend, $session->sessionend);
}
// Get all the chat sessions.
$allsessions = chat_get_sessions($messages, true);
// When showall is true, we should get 3 sessions.
$this->assertCount(3, $allsessions);
// Reverse sort sessions so they are in ascending order matching our expected session times and users.
$allsessions = array_reverse($allsessions);
foreach ($allsessions as $index => $session) {
// Check the session users.
$users = $sessionusers[$index];
$this->assertCount(count($users), $session->sessionusers);
// Check the message counts for each user in this session.
foreach ($users as $userid => $messagecount) {
$this->assertEquals($messagecount, $session->sessionusers[$userid]);
}
$sessionstart = $sessiontimes[$index]['start'];
$sessionend = $sessiontimes[$index]['end'];
$this->assertEquals($sessionstart, $session->sessionstart);
$this->assertEquals($sessionend, $session->sessionend);
}
}
public function test_chat_core_calendar_provide_event_action_already_completed(): void {
set_config('enablecompletion', 1);
$this->setAdminUser();
// Create the activity.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
// Get some additional data.
$cm = get_coursemodule_from_instance('chat', $chat->id);
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Mark the activity as completed.
$completion = new \completion_info($course);
$completion->set_module_viewed($cm);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
// Ensure result was null.
$this->assertNull($actionevent);
}
public function test_chat_core_calendar_provide_event_action_already_completed_for_user(): void {
set_config('enablecompletion', 1);
$this->setAdminUser();
// Create the activity.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
// Enrol a student in the course.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Get some additional data.
$cm = get_coursemodule_from_instance('chat', $chat->id);
// Create a calendar event.
$event = $this->create_action_event($course->id, $chat->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Mark the activity as completed for the student.
$completion = new \completion_info($course);
$completion->set_module_viewed($cm, $student->id);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
// Ensure result was null.
$this->assertNull($actionevent);
}
/**
* Creates an action event.
*
* @param int $courseid
* @param int $instanceid The chat id.
* @param string $eventtype The event type. eg. ASSIGN_EVENT_TYPE_DUE.
* @return bool|calendar_event
*/
private function create_action_event($courseid, $instanceid, $eventtype) {
$event = new \stdClass();
$event->name = 'Calendar event';
$event->modulename = 'chat';
$event->courseid = $courseid;
$event->instance = $instanceid;
$event->type = CALENDAR_EVENT_TYPE_ACTION;
$event->eventtype = $eventtype;
$event->timestart = time();
return \calendar_event::create($event);
}
/**
* A user who does not have capabilities to add events to the calendar should be able to create an chat.
*/
public function test_creation_with_no_calendar_capabilities(): void {
$this->resetAfterTest();
$course = self::getDataGenerator()->create_course();
$context = \context_course::instance($course->id);
$user = self::getDataGenerator()->create_and_enrol($course, 'editingteacher');
$roleid = self::getDataGenerator()->create_role();
self::getDataGenerator()->role_assign($roleid, $user->id, $context->id);
assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
$generator = self::getDataGenerator()->get_plugin_generator('mod_chat');
// Create an instance as a user without the calendar capabilities.
$this->setUser($user);
$params = array(
'course' => $course->id,
'chattime' => time() + 500,
);
$generator->create_instance($params);
}
}
+438
View File
@@ -0,0 +1,438 @@
<?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/>.
/**
* Data provider tests.
*
* @package mod_chat
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_chat\privacy;
defined('MOODLE_INTERNAL') || die();
global $CFG;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use mod_chat\privacy\provider;
require_once($CFG->dirroot . '/mod/chat/lib.php');
/**
* Data provider testcase class.
*
* @package mod_chat
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends provider_testcase {
public function setUp(): void {
global $PAGE;
$this->resetAfterTest();
$PAGE->get_renderer('core');
// Chat module is disabled by default, enable it for testing.
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
$manager::enable_plugin('chat', 1);
}
public function test_get_contexts_for_userid(): void {
global $DB;
$dg = $this->getDataGenerator();
$c1 = $dg->create_course();
$c2 = $dg->create_course();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$chat1a = $dg->create_module('chat', ['course' => $c1]);
$chat1b = $dg->create_module('chat', ['course' => $c1]);
$chat2a = $dg->create_module('chat', ['course' => $c2]);
// Logins but no message.
$chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1a);
// Logins and messages.
$chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1b);
chat_send_chatmessage($chatuser, 'Hello world!');
// Silent login (no system message).
$chatuser = $this->login_user_in_course_chat($u1, $c2, $chat2a, 0, true);
// Silent login and messages.
$chatuser = $this->login_user_in_course_chat($u2, $c1, $chat1b, 0, true);
chat_send_chatmessage($chatuser, 'Ça va ?');
chat_send_chatmessage($chatuser, 'Moi, ça va.');
// Silent login and messages.
$chatuser = $this->login_user_in_course_chat($u2, $c2, $chat2a);
chat_send_chatmessage($chatuser, 'What\'s happening here?');
// Check contexts for user 1.
$contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
$this->assertCount(2, $contextids);
$this->assertTrue(in_array(\context_module::instance($chat1a->cmid)->id, $contextids));
$this->assertTrue(in_array(\context_module::instance($chat1b->cmid)->id, $contextids));
$contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
$this->assertCount(2, $contextids);
$this->assertTrue(in_array(\context_module::instance($chat1b->cmid)->id, $contextids));
$this->assertTrue(in_array(\context_module::instance($chat2a->cmid)->id, $contextids));
}
/**
* Test that only users with relevant contexts are fetched.
*/
public function test_get_users_in_context(): void {
$component = 'mod_chat';
$dg = $this->getDataGenerator();
$c1 = $dg->create_course();
$c2 = $dg->create_course();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$chat1a = $dg->create_module('chat', ['course' => $c1]);
$chat1b = $dg->create_module('chat', ['course' => $c1]);
$chat2a = $dg->create_module('chat', ['course' => $c2]);
// Logins but no message.
$chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1a);
// Logins and messages.
$chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1b);
chat_send_chatmessage($chatuser, 'Hello world!');
// Silent login (no system message).
$chatuser = $this->login_user_in_course_chat($u1, $c2, $chat2a, 0, true);
// Silent login and messages.
$chatuser = $this->login_user_in_course_chat($u2, $c1, $chat1b, 0, true);
chat_send_chatmessage($chatuser, 'Ça va ?');
chat_send_chatmessage($chatuser, 'Moi, ça va.');
// Silent login and messages.
$chatuser = $this->login_user_in_course_chat($u2, $c2, $chat2a);
chat_send_chatmessage($chatuser, 'What\'s happening here?');
$context1a = \context_module::instance($chat1a->cmid);
$context1b = \context_module::instance($chat1b->cmid);
$context2a = \context_module::instance($chat2a->cmid);
$userlist1a = new \core_privacy\local\request\userlist($context1a, $component);
$userlist1b = new \core_privacy\local\request\userlist($context1b, $component);
$userlist2a = new \core_privacy\local\request\userlist($context2a, $component);
\mod_chat\privacy\provider::get_users_in_context($userlist1a);
\mod_chat\privacy\provider::get_users_in_context($userlist1b);
\mod_chat\privacy\provider::get_users_in_context($userlist2a);
// Ensure correct users are found in relevant contexts.
$this->assertCount(1, $userlist1a);
$expected = [$u1->id];
$actual = $userlist1a->get_userids();
$this->assertEquals($expected, $actual);
$this->assertCount(2, $userlist1b);
$expected = [$u1->id, $u2->id];
$actual = $userlist1b->get_userids();
sort($expected);
sort($actual);
$this->assertEquals($expected, $actual);
$this->assertCount(1, $userlist2a);
$expected = [$u1->id];
$actual = $userlist1a->get_userids();
$this->assertEquals($expected, $actual);
}
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
$dg = $this->getDataGenerator();
$c1 = $dg->create_course();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$chat1a = $dg->create_module('chat', ['course' => $c1]);
$chat1b = $dg->create_module('chat', ['course' => $c1]);
$chat1actx = \context_module::instance($chat1a->cmid);
$chat1bctx = \context_module::instance($chat1b->cmid);
$u1chat1a = $this->login_user_in_course_chat($u1, $c1, $chat1a);
$u2chat1a = $this->login_user_in_course_chat($u2, $c1, $chat1a);
chat_send_chatmessage($u1chat1a, 'Ça va ?');
chat_send_chatmessage($u2chat1a, 'Oui, et toi ?');
chat_send_chatmessage($u1chat1a, 'Bien merci.');
chat_send_chatmessage($u2chat1a, 'Pourquoi ils disent omelette "du" fromage ?!');
chat_send_chatmessage($u1chat1a, 'Aucune idée');
$this->assert_has_data_in_chat($u1, $chat1a);
$this->assert_has_data_in_chat($u2, $chat1a);
$u1chat1b = $this->login_user_in_course_chat($u1, $c1, $chat1b);
$u2chat1b = $this->login_user_in_course_chat($u2, $c1, $chat1b);
chat_send_chatmessage($u1chat1b, 'How are you going?');
chat_send_chatmessage($u2chat1b, 'Alright, you?');
chat_send_chatmessage($u1chat1b, 'Good, thanks.');
chat_send_chatmessage($u2chat1b, 'Sacre bleu!');
chat_send_chatmessage($u1chat1b, '\ö/');
$this->assert_has_data_in_chat($u1, $chat1b);
$this->assert_has_data_in_chat($u2, $chat1b);
// No change.
provider::delete_data_for_all_users_in_context(\context_course::instance($c1->id));
$this->assert_has_data_in_chat($u1, $chat1a);
$this->assert_has_data_in_chat($u2, $chat1a);
$this->assert_has_data_in_chat($u1, $chat1b);
$this->assert_has_data_in_chat($u2, $chat1b);
// Deletinge first chat does not affect other chat.
provider::delete_data_for_all_users_in_context($chat1actx);
$this->assert_has_no_data_in_chat($u1, $chat1a);
$this->assert_has_no_data_in_chat($u2, $chat1a);
$this->assert_has_data_in_chat($u1, $chat1b);
$this->assert_has_data_in_chat($u2, $chat1b);
}
public function test_delete_data_for_user(): void {
global $DB;
$dg = $this->getDataGenerator();
$c1 = $dg->create_course();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$chat1a = $dg->create_module('chat', ['course' => $c1]);
$chat1b = $dg->create_module('chat', ['course' => $c1]);
$chat1actx = \context_module::instance($chat1a->cmid);
$chat1bctx = \context_module::instance($chat1b->cmid);
$u1chat1a = $this->login_user_in_course_chat($u1, $c1, $chat1a);
$u2chat1a = $this->login_user_in_course_chat($u2, $c1, $chat1a);
chat_send_chatmessage($u1chat1a, 'Ça va ?');
chat_send_chatmessage($u2chat1a, 'Oui, et toi ?');
chat_send_chatmessage($u1chat1a, 'Bien merci.');
chat_send_chatmessage($u2chat1a, 'Pourquoi ils disent omelette "du" fromage ?!');
chat_send_chatmessage($u1chat1a, 'Aucune idée');
$this->assert_has_data_in_chat($u1, $chat1a);
$this->assert_has_data_in_chat($u2, $chat1a);
$u1chat1b = $this->login_user_in_course_chat($u1, $c1, $chat1b);
$u2chat1b = $this->login_user_in_course_chat($u2, $c1, $chat1b);
chat_send_chatmessage($u1chat1b, 'How are you going?');
chat_send_chatmessage($u2chat1b, 'Alright, you?');
chat_send_chatmessage($u1chat1b, 'Good, thanks.');
chat_send_chatmessage($u2chat1b, 'Sacre bleu!');
chat_send_chatmessage($u1chat1b, '\ö/');
$this->assert_has_data_in_chat($u1, $chat1b);
$this->assert_has_data_in_chat($u2, $chat1b);
provider::delete_data_for_user(new approved_contextlist($u1, 'mod_chat', [$chat1actx->id]));
$this->assert_has_no_data_in_chat($u1, $chat1a);
$this->assert_has_data_in_chat($u2, $chat1a);
$this->assert_has_data_in_chat($u1, $chat1b);
$this->assert_has_data_in_chat($u2, $chat1b);
provider::delete_data_for_user(new approved_contextlist($u2, 'mod_chat', [$chat1actx->id, $chat1bctx->id]));
$this->assert_has_no_data_in_chat($u1, $chat1a);
$this->assert_has_no_data_in_chat($u2, $chat1a);
$this->assert_has_data_in_chat($u1, $chat1b);
$this->assert_has_no_data_in_chat($u2, $chat1b);
}
/**
* Test that data for users in approved userlist is deleted.
*/
public function test_delete_data_for_users(): void {
global $DB;
$component = 'mod_chat';
$dg = $this->getDataGenerator();
$c1 = $dg->create_course();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$u3 = $dg->create_user();
$chat1 = $dg->create_module('chat', ['course' => $c1]);
$chat1context = \context_module::instance($chat1->cmid);
$u1chat1 = $this->login_user_in_course_chat($u1, $c1, $chat1);
$u2chat1 = $this->login_user_in_course_chat($u2, $c1, $chat1);
$u3chat1 = $this->login_user_in_course_chat($u3, $c1, $chat1);
chat_send_chatmessage($u1chat1, 'Ça va ?');
chat_send_chatmessage($u2chat1, 'Oui, et toi ?');
chat_send_chatmessage($u1chat1, 'Bien merci.');
chat_send_chatmessage($u2chat1, 'Pourquoi ils disent omelette "du" fromage ?!');
chat_send_chatmessage($u1chat1, 'Aucune idée');
chat_send_chatmessage($u3chat1, 'Je ne comprends pas');
$this->assert_has_data_in_chat($u1, $chat1);
$this->assert_has_data_in_chat($u2, $chat1);
$this->assert_has_data_in_chat($u3, $chat1);
$chat2 = $dg->create_module('chat', ['course' => $c1]);
$u1chat2 = $this->login_user_in_course_chat($u1, $c1, $chat2);
$u2chat2 = $this->login_user_in_course_chat($u2, $c1, $chat2);
$u3chat2 = $this->login_user_in_course_chat($u3, $c1, $chat2);
chat_send_chatmessage($u1chat2, 'Why do we have a separate chat?');
chat_send_chatmessage($u2chat2, 'I have no idea!');
chat_send_chatmessage($u3chat2, 'Me either.');
$this->assert_has_data_in_chat($u1, $chat2);
$this->assert_has_data_in_chat($u2, $chat2);
$this->assert_has_data_in_chat($u3, $chat2);
// Delete user 1 and 2 data from chat 1 context only.
$approveduserids = [$u1->id, $u2->id];
$approvedlist = new approved_userlist($chat1context, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
// Ensure correct chat data is deleted.
$this->assert_has_no_data_in_chat($u1, $chat1);
$this->assert_has_no_data_in_chat($u2, $chat1);
$this->assert_has_data_in_chat($u3, $chat1);
$this->assert_has_data_in_chat($u1, $chat2);
$this->assert_has_data_in_chat($u2, $chat2);
$this->assert_has_data_in_chat($u3, $chat2);
}
public function test_export_data_for_user(): void {
global $DB;
$dg = $this->getDataGenerator();
$c1 = $dg->create_course();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$chat1a = $dg->create_module('chat', ['course' => $c1]);
$chat1b = $dg->create_module('chat', ['course' => $c1]);
$chat1actx = \context_module::instance($chat1a->cmid);
$chat1bctx = \context_module::instance($chat1b->cmid);
$u1chat1a = $this->login_user_in_course_chat($u1, $c1, $chat1a);
$u2chat1a = $this->login_user_in_course_chat($u2, $c1, $chat1a);
chat_send_chatmessage($u1chat1a, 'Ça va ?');
chat_send_chatmessage($u2chat1a, 'Oui, et toi ?');
chat_send_chatmessage($u1chat1a, 'Bien merci.');
chat_send_chatmessage($u2chat1a, 'Pourquoi ils disent omelette "du" fromage ?!');
chat_send_chatmessage($u1chat1a, 'Aucune idée');
chat_send_chatmessage($u1chat1a, 'exit', true);
$u1chat1b = $this->login_user_in_course_chat($u1, $c1, $chat1b);
$u2chat1b = $this->login_user_in_course_chat($u2, $c1, $chat1b);
chat_send_chatmessage($u1chat1b, 'How are you going?');
chat_send_chatmessage($u2chat1b, 'Alright, you?');
chat_send_chatmessage($u1chat1b, 'Good, thanks.');
chat_send_chatmessage($u2chat1b, 'Sacre bleu!');
chat_send_chatmessage($u1chat1b, '\ö/');
// Export for user 1 in chat 1.
provider::export_user_data(new approved_contextlist($u1, 'mod_chat', [$chat1actx->id]));
$data = writer::with_context($chat1actx)->get_data([]);
$this->assertNotEmpty($data);
$this->assertCount(5, $data->messages);
$this->assertEquals(get_string('messageenter', 'mod_chat', fullname($u1)), $data->messages[0]['message']);
$this->assertEquals(transform::yesno(true), $data->messages[0]['is_system_generated']);
$this->assertEquals('Ça va ?', $data->messages[1]['message']);
$this->assertEquals(transform::yesno(false), $data->messages[1]['is_system_generated']);
$this->assertEquals('Bien merci.', $data->messages[2]['message']);
$this->assertEquals(transform::yesno(false), $data->messages[2]['is_system_generated']);
$this->assertEquals('Aucune idée', $data->messages[3]['message']);
$this->assertEquals(transform::yesno(false), $data->messages[3]['is_system_generated']);
$this->assertEquals(get_string('messageexit', 'mod_chat', fullname($u1)), $data->messages[4]['message']);
$this->assertEquals(transform::yesno(true), $data->messages[4]['is_system_generated']);
$data = writer::with_context($chat1bctx)->get_data([]);
$this->assertEmpty($data);
// Export for user2 in chat 1 and 2.
writer::reset();
provider::export_user_data(new approved_contextlist($u2, 'mod_chat', [$chat1actx->id, $chat1bctx->id]));
$data = writer::with_context($chat1actx)->get_data([]);
$this->assertNotEmpty($data);
$this->assertCount(3, $data->messages);
$this->assertEquals(get_string('messageenter', 'mod_chat', fullname($u2)), $data->messages[0]['message']);
$this->assertEquals('Oui, et toi ?', $data->messages[1]['message']);
$this->assertEquals('Pourquoi ils disent omelette "du" fromage ?!', $data->messages[2]['message']);
$data = writer::with_context($chat1bctx)->get_data([]);
$this->assertNotEmpty($data);
$this->assertCount(3, $data->messages);
$this->assertEquals(get_string('messageenter', 'mod_chat', fullname($u2)), $data->messages[0]['message']);
$this->assertEquals('Alright, you?', $data->messages[1]['message']);
$this->assertEquals('Sacre bleu!', $data->messages[2]['message']);
}
/**
* Assert that there is data for a user in a chat.
*
* @param object $user The user.
* @param object $chat The chat.
* @return void
*/
protected function assert_has_data_in_chat($user, $chat) {
$this->assertTrue($this->has_data_in_chat($user, $chat));
}
/**
* Assert that there isn't any data for a user in a chat.
*
* @param object $user The user.
* @param object $chat The chat.
* @return void
*/
protected function assert_has_no_data_in_chat($user, $chat) {
$this->assertFalse($this->has_data_in_chat($user, $chat));
}
/**
* Check whether a user has data in a chat.
*
* @param object $user The user.
* @param object $chat The chat.
* @return bool
*/
protected function has_data_in_chat($user, $chat) {
global $DB;
return $DB->record_exists('chat_messages', ['chatid' => $chat->id, 'userid' => $user->id]);
}
/**
* Login a user in a chat.
*
* @param object $user The user.
* @param object $course The course.
* @param object $chat The chat.
* @param int $group The group number.
* @param bool $silent Whether we should advertise that the user logs in.
* @return object The chat user.
*/
protected function login_user_in_course_chat($user, $course, $chat, $group = 0, $silent = false) {
global $DB, $USER;
$origuser = $USER;
$this->setUser($user);
chat_login_user($chat->id, $silent ? 'sockets' : 'basic', 0, $course);
$chatuser = $DB->get_record('chat_users', ['userid' => $user->id, 'chatid' => $chat->id, 'groupid' => 0]);
$this->setUser($origuser);
return $chatuser;
}
}