2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 * Contains class containing unit tests for mod/chat/lib.php.
22 * @copyright 2017 Mark Nelson <markn@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') ||
die();
30 * Class containing unit tests for mod/chat/lib.php.
34 * @copyright 2017 Mark Nelson <markn@moodle.com>
35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 class lib_test
extends \advanced_testcase
{
39 public function setUp(): void
{
40 $this->resetAfterTest();
42 // Chat module is disabled by default, enable it for testing.
43 $manager = \core_plugin_manager
::resolve_plugininfo_class('mod');
44 $manager::enable_plugin('chat', 1);
48 * The chat's event should not be shown to a user when the user cannot view the chat at all.
50 public function test_chat_core_calendar_provide_event_action_in_hidden_section() {
53 $this->setAdminUser();
56 $course = $this->getDataGenerator()->create_course();
59 $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
62 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
63 'chattime' => usergetmidnight(time())));
65 // Create a calendar event.
66 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
68 // Set sections 0 as hidden.
69 set_section_visible($course->id
, 0, 0);
72 $CFG->forcelogin
= true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
75 // Create an action factory.
76 $factory = new \core_calendar\action_factory
();
78 // Decorate action event for the student.
79 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id
);
81 // Confirm the event is not shown at all.
82 $this->assertNull($actionevent);
86 * The chat's event should not be shown to a user who does not have permission to view the chat at all.
88 public function test_chat_core_calendar_provide_event_action_for_non_user() {
91 $this->setAdminUser();
94 $course = $this->getDataGenerator()->create_course();
97 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
98 'chattime' => usergetmidnight(time())));
100 // Create a calendar event.
101 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
104 $CFG->forcelogin
= true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
107 // Create an action factory.
108 $factory = new \core_calendar\action_factory
();
110 // Decorate action event.
111 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
113 // Confirm the event is not shown at all.
114 $this->assertNull($actionevent);
117 public function test_chat_core_calendar_provide_event_action_chattime_event_yesterday() {
118 $this->setAdminUser();
121 $course = $this->getDataGenerator()->create_course();
124 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
125 'chattime' => time() - DAYSECS
));
127 // Create a calendar event.
128 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
130 // Create an action factory.
131 $factory = new \core_calendar\action_factory
();
133 // Decorate action event.
134 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
136 // Confirm the event is not shown at all.
137 $this->assertNull($actionevent);
140 public function test_chat_core_calendar_provide_event_action_chattime_event_yesterday_for_user() {
143 $this->setAdminUser();
146 $course = $this->getDataGenerator()->create_course();
148 // Enrol a student in the course.
149 $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
152 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
153 'chattime' => time() - DAYSECS
));
155 // Create a calendar event.
156 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
159 $CFG->forcelogin
= true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
162 // Create an action factory.
163 $factory = new \core_calendar\action_factory
();
165 // Decorate action event for the student.
166 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id
);
168 // Confirm the event is not shown at all.
169 $this->assertNull($actionevent);
172 public function test_chat_core_calendar_provide_event_action_chattime_event_today() {
173 $this->setAdminUser();
176 $course = $this->getDataGenerator()->create_course();
179 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
180 'chattime' => usergetmidnight(time())));
182 // Create a calendar event.
183 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
185 // Create an action factory.
186 $factory = new \core_calendar\action_factory
();
188 // Decorate action event.
189 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
191 // Confirm the event was decorated.
192 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
193 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
194 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
195 $this->assertEquals(1, $actionevent->get_item_count());
196 $this->assertTrue($actionevent->is_actionable());
199 public function test_chat_core_calendar_provide_event_action_chattime_event_today_for_user() {
202 $this->setAdminUser();
205 $course = $this->getDataGenerator()->create_course();
207 // Enrol a student in the course.
208 $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
211 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
212 'chattime' => usergetmidnight(time())));
214 // Create a calendar event.
215 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
218 $CFG->forcelogin
= true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
221 // Create an action factory.
222 $factory = new \core_calendar\action_factory
();
224 // Decorate action event for the student.
225 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id
);
227 // Confirm the event was decorated.
228 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
229 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
230 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
231 $this->assertEquals(1, $actionevent->get_item_count());
232 $this->assertTrue($actionevent->is_actionable());
235 public function test_chat_core_calendar_provide_event_action_chattime_event_tonight() {
236 $this->setAdminUser();
239 $course = $this->getDataGenerator()->create_course();
242 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
243 'chattime' => usergetmidnight(time()) +
(23 * HOURSECS
)));
245 // Create a calendar event.
246 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
248 // Create an action factory.
249 $factory = new \core_calendar\action_factory
();
251 // Decorate action event.
252 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
254 // Confirm the event was decorated.
255 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
256 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
257 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
258 $this->assertEquals(1, $actionevent->get_item_count());
259 $this->assertTrue($actionevent->is_actionable());
262 public function test_chat_core_calendar_provide_event_action_chattime_event_tonight_for_user() {
265 $this->setAdminUser();
268 $course = $this->getDataGenerator()->create_course();
270 // Enrol a student in the course.
271 $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
274 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
275 'chattime' => usergetmidnight(time()) +
(23 * HOURSECS
)));
277 // Create a calendar event.
278 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
281 $CFG->forcelogin
= true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
284 // Create an action factory.
285 $factory = new \core_calendar\action_factory
();
287 // Decorate action event for the student.
288 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id
);
290 // Confirm the event was decorated.
291 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
292 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
293 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
294 $this->assertEquals(1, $actionevent->get_item_count());
295 $this->assertTrue($actionevent->is_actionable());
298 public function test_chat_core_calendar_provide_event_action_chattime_event_tomorrow() {
299 $this->setAdminUser();
302 $course = $this->getDataGenerator()->create_course();
305 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
306 'chattime' => time() + DAYSECS
));
308 // Create a calendar event.
309 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
311 // Create an action factory.
312 $factory = new \core_calendar\action_factory
();
314 // Decorate action event.
315 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
317 // Confirm the event was decorated.
318 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
319 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
320 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
321 $this->assertEquals(1, $actionevent->get_item_count());
322 $this->assertFalse($actionevent->is_actionable());
325 public function test_chat_core_calendar_provide_event_action_chattime_event_tomorrow_for_user() {
328 $this->setAdminUser();
331 $course = $this->getDataGenerator()->create_course();
333 // Enrol a student in the course.
334 $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
337 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
338 'chattime' => time() + DAYSECS
));
340 // Create a calendar event.
341 $event = $this->create_action_event($course->id
, $chat->id
, CHAT_EVENT_TYPE_CHATTIME
);
344 $CFG->forcelogin
= true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
347 // Create an action factory.
348 $factory = new \core_calendar\action_factory
();
350 // Decorate action event for the student.
351 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id
);
353 // Confirm the event was decorated.
354 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
355 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
356 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
357 $this->assertEquals(1, $actionevent->get_item_count());
358 $this->assertFalse($actionevent->is_actionable());
361 public function test_chat_core_calendar_provide_event_action_chattime_event_different_timezones() {
364 $this->setAdminUser();
367 $course = $this->getDataGenerator()->create_course();
371 // This could have been much easier if MDL-37327 were implemented.
372 // We don't know when this test is being ran and there is no standard way to
373 // mock the time() function (MDL-37327 to handle that).
375 $timezone1 = 'UTC'; // GMT.
376 $timezone2 = 'Pacific/Pago_Pago'; // GMT -11:00.
377 } else if ($hour < 11) {
378 $timezone1 = 'Pacific/Kiritimati'; // GMT +14:00.
379 $timezone2 = 'America/Sao_Paulo'; // GMT -03:00.
381 $timezone1 = 'Pacific/Kiritimati'; // GMT +14:00.
382 $timezone2 = 'UTC'; // GMT.
385 $this->setTimezone($timezone2);
387 // Enrol 2 students with different timezones in the course.
388 $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student', (object)['timezone' => $timezone1]);
389 $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student', (object)['timezone' => $timezone2]);
392 $chat1 = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
393 'chattime' => mktime(1, 0, 0))); // This is always yesterday in timezone1 time
394 // and always today in timezone2 time.
397 $chat2 = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
,
398 'chattime' => mktime(1, 0, 0) + DAYSECS
)); // This is always today in timezone1 time
399 // and always tomorrow in timezone2 time.
401 // Create calendar events for the 2 chats above.
402 $event1 = $this->create_action_event($course->id
, $chat1->id
, CHAT_EVENT_TYPE_CHATTIME
);
403 $event2 = $this->create_action_event($course->id
, $chat2->id
, CHAT_EVENT_TYPE_CHATTIME
);
406 $CFG->forcelogin
= true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
409 // Create an action factory.
410 $factory = new \core_calendar\action_factory
();
412 // Decorate action event for student1.
413 $actionevent11 = mod_chat_core_calendar_provide_event_action($event1, $factory, $student1->id
);
414 $actionevent12 = mod_chat_core_calendar_provide_event_action($event1, $factory, $student2->id
);
415 $actionevent21 = mod_chat_core_calendar_provide_event_action($event2, $factory, $student1->id
);
416 $actionevent22 = mod_chat_core_calendar_provide_event_action($event2, $factory, $student2->id
);
418 // Confirm event1 is not shown to student1 at all.
419 $this->assertNull($actionevent11, 'Failed for UTC time ' . gmdate('H:i'));
421 // Confirm event1 was decorated for student2 and it is actionable.
422 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent12);
423 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent12->get_name());
424 $this->assertInstanceOf('moodle_url', $actionevent12->get_url());
425 $this->assertEquals(1, $actionevent12->get_item_count());
426 $this->assertTrue($actionevent12->is_actionable());
428 // Confirm event2 was decorated for student1 and it is actionable.
429 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent21);
430 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent21->get_name());
431 $this->assertInstanceOf('moodle_url', $actionevent21->get_url());
432 $this->assertEquals(1, $actionevent21->get_item_count());
433 $this->assertTrue($actionevent21->is_actionable());
435 // Confirm event2 was decorated for student2 and it is not actionable.
436 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent22);
437 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent22->get_name());
438 $this->assertInstanceOf('moodle_url', $actionevent22->get_url());
439 $this->assertEquals(1, $actionevent22->get_item_count());
440 $this->assertFalse($actionevent22->is_actionable());
444 * Test for chat_get_sessions().
446 public function test_chat_get_sessions() {
449 $this->resetAfterTest();
451 $generator = $this->getDataGenerator();
454 $this->setAdminUser();
455 $course = $generator->create_course();
456 $chat = $generator->create_module('chat', ['course' => $course->id
]);
458 $user1 = $generator->create_user();
459 $user2 = $generator->create_user();
460 $studentrole = $DB->get_record('role', ['shortname' => 'student']);
461 $generator->enrol_user($user1->id
, $course->id
, $studentrole->id
);
462 $generator->enrol_user($user2->id
, $course->id
, $studentrole->id
);
465 $this->setUser($user1);
466 $chatsid = chat_login_user($chat->id
, 'ajax', 0, $course);
467 $chatuser = $DB->get_record('chat_users', ['sid' => $chatsid]);
469 // Get the messages for this chat session.
470 $messages = chat_get_session_messages($chat->id
, false, 0, 0, 'timestamp DESC');
472 // We should have just 1 system (enter) messages.
473 $this->assertCount(1, $messages);
475 // This is when the session starts (when the first message - enter - has been sent).
476 $sessionstart = reset($messages)->timestamp
;
478 // Send some messages.
479 chat_send_chatmessage($chatuser, 'hello!');
480 chat_send_chatmessage($chatuser, 'bye bye!');
483 $this->setUser($user2);
484 $chatsid = chat_login_user($chat->id
, 'ajax', 0, $course);
485 $chatuser = $DB->get_record('chat_users', ['sid' => $chatsid]);
487 // Send a message and take note of this message ID.
488 $messageid = chat_send_chatmessage($chatuser, 'greetings!');
490 // This is when the session ends (timestamp of the last message sent to the chat).
491 $sessionend = $DB->get_field('chat_messages', 'timestamp', ['id' => $messageid]);
493 // Get the messages for this chat session.
494 $messages = chat_get_session_messages($chat->id
, false, 0, 0, 'timestamp DESC');
496 // We should have 3 user and 2 system (enter) messages.
497 $this->assertCount(5, $messages);
499 // Fetch the chat sessions from the messages we retrieved.
500 $sessions = chat_get_sessions($messages, true);
502 // There should be only one session.
503 $this->assertCount(1, $sessions);
506 $session = reset($sessions);
508 // Confirm that the start and end times of the session matches.
509 $this->assertEquals($sessionstart, $session->sessionstart
);
510 $this->assertEquals($sessionend, $session->sessionend
);
511 // Confirm we have 2 participants in the chat.
512 $this->assertCount(2, $session->sessionusers
);
516 * Test for chat_get_sessions with messages belonging to multiple sessions.
518 public function test_chat_get_sessions_multiple() {
525 // Messages belonging to 3 sessions. Session 1 has 10 messages, 2 has 15, 3 has 25.
528 $session = 0; // Incomplete session.
529 for ($i = 1; $i <= 50; $i++
) {
530 // Take note of expected session times as we go through.
533 // Session 1 start time.
534 $sessiontimes[0]['start'] = $timestamp;
537 // Session 1 end time.
538 $sessiontimes[0]['end'] = $timestamp;
541 // Session 2 start time.
542 $sessiontimes[1]['start'] = $timestamp;
545 // Session 2 end time.
546 $sessiontimes[1]['end'] = $timestamp;
549 // Session 3 start time.
550 $sessiontimes[2]['start'] = $timestamp;
553 // Session 3 end time.
554 $sessiontimes[2]['end'] = $timestamp;
561 // Let's also include system messages as well. Give them to pop in 1-in-10 chance.
562 $issystem = rand(1, 10) == 10;
567 $message = 'Message ' . $i;
568 if (!isset($sessionusers[$session][$user])) {
569 $sessionusers[$session][$user] = 1;
571 $sessionusers[$session][$user]++
;
574 $messages[] = (object)[
578 'message' => $message,
579 'issystem' => $issystem,
580 'timestamp' => $timestamp,
583 // Set the next timestamp.
584 if ($i == 10 ||
$i == 25) {
587 $timestamp +
= CHAT_SESSION_GAP +
1;
592 // Reverse sort the messages so they're in descending order.
595 // Get chat sessions showing only complete ones.
596 $completesessions = chat_get_sessions($messages);
597 // Session 1 is incomplete, so there should only be 2 sessions when $showall is false.
598 $this->assertCount(2, $completesessions);
600 // Reverse sort sessions so they are in ascending order matching our expected session times and users.
601 $completesessions = array_reverse($completesessions);
602 foreach ($completesessions as $index => $session) {
603 // We increment index by 1 because the incomplete expected session (index=0) is not included.
604 $expectedindex = $index +
1;
606 // Check the session users.
607 $users = $sessionusers[$expectedindex];
608 $this->assertCount(count($users), $session->sessionusers
);
609 // Check the message counts for each user in this session.
610 foreach ($users as $userid => $messagecount) {
611 $this->assertEquals($messagecount, $session->sessionusers
[$userid]);
614 $sessionstart = $sessiontimes[$expectedindex]['start'];
615 $sessionend = $sessiontimes[$expectedindex]['end'];
616 $this->assertEquals($sessionstart, $session->sessionstart
);
617 $this->assertEquals($sessionend, $session->sessionend
);
620 // Get all the chat sessions.
621 $allsessions = chat_get_sessions($messages, true);
622 // When showall is true, we should get 3 sessions.
623 $this->assertCount(3, $allsessions);
625 // Reverse sort sessions so they are in ascending order matching our expected session times and users.
626 $allsessions = array_reverse($allsessions);
627 foreach ($allsessions as $index => $session) {
628 // Check the session users.
629 $users = $sessionusers[$index];
630 $this->assertCount(count($users), $session->sessionusers
);
631 // Check the message counts for each user in this session.
632 foreach ($users as $userid => $messagecount) {
633 $this->assertEquals($messagecount, $session->sessionusers
[$userid]);
636 $sessionstart = $sessiontimes[$index]['start'];
637 $sessionend = $sessiontimes[$index]['end'];
638 $this->assertEquals($sessionstart, $session->sessionstart
);
639 $this->assertEquals($sessionend, $session->sessionend
);
643 public function test_chat_core_calendar_provide_event_action_already_completed() {
644 set_config('enablecompletion', 1);
645 $this->setAdminUser();
647 // Create the activity.
648 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
649 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
),
650 array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS
));
652 // Get some additional data.
653 $cm = get_coursemodule_from_instance('chat', $chat->id
);
655 // Create a calendar event.
656 $event = $this->create_action_event($course->id
, $chat->id
,
657 \core_completion\api
::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED
);
659 // Mark the activity as completed.
660 $completion = new \
completion_info($course);
661 $completion->set_module_viewed($cm);
663 // Create an action factory.
664 $factory = new \core_calendar\action_factory
();
666 // Decorate action event.
667 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
669 // Ensure result was null.
670 $this->assertNull($actionevent);
673 public function test_chat_core_calendar_provide_event_action_already_completed_for_user() {
674 set_config('enablecompletion', 1);
675 $this->setAdminUser();
677 // Create the activity.
678 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
679 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id
),
680 array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS
));
682 // Enrol a student in the course.
683 $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
685 // Get some additional data.
686 $cm = get_coursemodule_from_instance('chat', $chat->id
);
688 // Create a calendar event.
689 $event = $this->create_action_event($course->id
, $chat->id
,
690 \core_completion\api
::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED
);
692 // Mark the activity as completed for the student.
693 $completion = new \
completion_info($course);
694 $completion->set_module_viewed($cm, $student->id
);
696 // Create an action factory.
697 $factory = new \core_calendar\action_factory
();
699 // Decorate action event for the student.
700 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id
);
702 // Ensure result was null.
703 $this->assertNull($actionevent);
707 * Creates an action event.
709 * @param int $courseid
710 * @param int $instanceid The chat id.
711 * @param string $eventtype The event type. eg. ASSIGN_EVENT_TYPE_DUE.
712 * @return bool|calendar_event
714 private function create_action_event($courseid, $instanceid, $eventtype) {
715 $event = new \
stdClass();
716 $event->name
= 'Calendar event';
717 $event->modulename
= 'chat';
718 $event->courseid
= $courseid;
719 $event->instance
= $instanceid;
720 $event->type
= CALENDAR_EVENT_TYPE_ACTION
;
721 $event->eventtype
= $eventtype;
722 $event->timestart
= time();
724 return \calendar_event
::create($event);
728 * A user who does not have capabilities to add events to the calendar should be able to create an chat.
730 public function test_creation_with_no_calendar_capabilities() {
731 $this->resetAfterTest();
732 $course = self
::getDataGenerator()->create_course();
733 $context = \context_course
::instance($course->id
);
734 $user = self
::getDataGenerator()->create_and_enrol($course, 'editingteacher');
735 $roleid = self
::getDataGenerator()->create_role();
736 self
::getDataGenerator()->role_assign($roleid, $user->id
, $context->id
);
737 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT
, $roleid, $context, true);
738 $generator = self
::getDataGenerator()->get_plugin_generator('mod_chat');
739 // Create an instance as a user without the calendar capabilities.
740 $this->setUser($user);
742 'course' => $course->id
,
743 'chattime' => time() +
500,
745 $generator->create_instance($params);