MDL-63097 phpunit: decouple user lastping and session start in tests
[moodle.git] / mod / chat / tests / lib_test.php
CommitLineData
bea71d57
MN
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
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.
8//
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.
13//
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/>.
16
17/**
18 * Contains class containing unit tests for mod/chat/lib.php.
19 *
20 * @package mod_chat
21 * @category test
22 * @copyright 2017 Mark Nelson <markn@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28/**
29 * Class containing unit tests for mod/chat/lib.php.
30 *
31 * @package mod_chat
32 * @category test
33 * @copyright 2017 Mark Nelson <markn@moodle.com>
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 */
36class mod_chat_lib_testcase extends advanced_testcase {
37
38 public function setUp() {
39 $this->resetAfterTest();
40 }
41
3b2be06b 42 public function test_chat_core_calendar_provide_event_action_chattime_event_yesterday() {
bea71d57
MN
43 $this->setAdminUser();
44
45 // Create a course.
46 $course = $this->getDataGenerator()->create_course();
47
48 // Create a chat.
3b2be06b
AN
49 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
50 'chattime' => time() - DAYSECS));
bea71d57
MN
51
52 // Create a calendar event.
53 $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
54
73be2a88
AN
55 // Create an action factory.
56 $factory = new \core_calendar\action_factory();
57
73be2a88
AN
58 // Decorate action event.
59 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
60
3b2be06b 61 // Confirm the event is not shown at all.
73be2a88 62 $this->assertNull($actionevent);
bea71d57
MN
63 }
64
3b2be06b 65 public function test_chat_core_calendar_provide_event_action_chattime_event_today() {
bea71d57
MN
66 $this->setAdminUser();
67
68 // Create a course.
69 $course = $this->getDataGenerator()->create_course();
70
71 // Create a chat.
3b2be06b
AN
72 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
73 'chattime' => usergetmidnight(time())));
74
75 // Create a calendar event.
76 $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
77
78 // Create an action factory.
79 $factory = new \core_calendar\action_factory();
80
81 // Decorate action event.
82 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
83
84 // Confirm the event was decorated.
85 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
86 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
87 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
88 $this->assertEquals(1, $actionevent->get_item_count());
89 $this->assertTrue($actionevent->is_actionable());
90 }
91
92 public function test_chat_core_calendar_provide_event_action_chattime_event_tonight() {
93 $this->setAdminUser();
94
95 // Create a course.
96 $course = $this->getDataGenerator()->create_course();
97
98 // Create a chat.
99 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
100 'chattime' => usergetmidnight(time()) + (23 * HOURSECS)));
bea71d57
MN
101
102 // Create a calendar event.
103 $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
104
105 // Create an action factory.
106 $factory = new \core_calendar\action_factory();
107
108 // Decorate action event.
109 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
110
111 // Confirm the event was decorated.
112 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
113 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
114 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
115 $this->assertEquals(1, $actionevent->get_item_count());
116 $this->assertTrue($actionevent->is_actionable());
117 }
118
3b2be06b 119 public function test_chat_core_calendar_provide_event_action_chattime_event_tomorrow() {
bea71d57
MN
120 $this->setAdminUser();
121
122 // Create a course.
123 $course = $this->getDataGenerator()->create_course();
124
125 // Create a chat.
126 $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
127 'chattime' => time() + DAYSECS));
128
129 // Create a calendar event.
130 $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
131
132 // Create an action factory.
133 $factory = new \core_calendar\action_factory();
134
135 // Decorate action event.
136 $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
137
138 // Confirm the event was decorated.
139 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
140 $this->assertEquals(get_string('enterchat', 'chat'), $actionevent->get_name());
141 $this->assertInstanceOf('moodle_url', $actionevent->get_url());
142 $this->assertEquals(1, $actionevent->get_item_count());
143 $this->assertFalse($actionevent->is_actionable());
144 }
145
70175dbe
JP
146 /**
147 * Test for chat_get_sessions().
148 */
149 public function test_chat_get_sessions() {
150 global $DB;
151
152 $this->resetAfterTest();
153
154 $generator = $this->getDataGenerator();
155
156 // Setup test data.
157 $this->setAdminUser();
158 $course = $generator->create_course();
159 $chat = $generator->create_module('chat', ['course' => $course->id]);
160
161 $user1 = $generator->create_user();
162 $user2 = $generator->create_user();
163 $studentrole = $DB->get_record('role', ['shortname' => 'student']);
164 $generator->enrol_user($user1->id, $course->id, $studentrole->id);
165 $generator->enrol_user($user2->id, $course->id, $studentrole->id);
166
167 // Login as user 1.
168 $this->setUser($user1);
169 $chatsid = chat_login_user($chat->id, 'ajax', 0, $course);
170 $chatuser = $DB->get_record('chat_users', ['sid' => $chatsid]);
171
2bf974e7
EL
172 // Get the messages for this chat session.
173 $messages = chat_get_session_messages($chat->id, false, 0, 0, 'timestamp DESC');
174
175 // We should have just 1 system (enter) messages.
176 $this->assertCount(1, $messages);
177
178 // This is when the session starts (when the first message - enter - has been sent).
179 $sessionstart = reset($messages)->timestamp;
70175dbe
JP
180
181 // Send some messages.
182 chat_send_chatmessage($chatuser, 'hello!');
183 chat_send_chatmessage($chatuser, 'bye bye!');
184
185 // Login as user 2.
186 $this->setUser($user2);
187 $chatsid = chat_login_user($chat->id, 'ajax', 0, $course);
188 $chatuser = $DB->get_record('chat_users', ['sid' => $chatsid]);
189
190 // Send a message and take note of this message ID.
191 $messageid = chat_send_chatmessage($chatuser, 'greetings!');
192
193 // This is when the session ends (timestamp of the last message sent to the chat).
194 $sessionend = $DB->get_field('chat_messages', 'timestamp', ['id' => $messageid]);
195
196 // Get the messages for this chat session.
197 $messages = chat_get_session_messages($chat->id, false, 0, 0, 'timestamp DESC');
198
199 // We should have 3 user and 2 system (enter) messages.
200 $this->assertCount(5, $messages);
201
202 // Fetch the chat sessions from the messages we retrieved.
203 $sessions = chat_get_sessions($messages, true);
204
205 // There should be only one session.
206 $this->assertCount(1, $sessions);
207
208 // Get this session.
209 $session = reset($sessions);
210
211 // Confirm that the start and end times of the session matches.
212 $this->assertEquals($sessionstart, $session->sessionstart);
213 $this->assertEquals($sessionend, $session->sessionend);
214 // Confirm we have 2 participants in the chat.
215 $this->assertCount(2, $session->sessionusers);
216 }
217
218 /**
219 * Test for chat_get_sessions with messages belonging to multiple sessions.
220 */
221 public function test_chat_get_sessions_multiple() {
222 $messages = [];
70175dbe
JP
223 $gap = 5; // 5 secs.
224
225 $now = time();
226 $timestamp = $now;
227
228 // Messages belonging to 3 sessions. Session 1 has 10 messages, 2 has 15, 3 has 25.
229 $sessionusers = [];
230 $sessiontimes = [];
231 $session = 0; // Incomplete session.
232 for ($i = 1; $i <= 50; $i++) {
233 // Take note of expected session times as we go through.
234 switch ($i) {
235 case 1:
236 // Session 1 start time.
237 $sessiontimes[0]['start'] = $timestamp;
238 break;
239 case 10:
240 // Session 1 end time.
241 $sessiontimes[0]['end'] = $timestamp;
242 break;
243 case 11:
244 // Session 2 start time.
245 $sessiontimes[1]['start'] = $timestamp;
246 break;
247 case 25:
248 // Session 2 end time.
249 $sessiontimes[1]['end'] = $timestamp;
250 break;
251 case 26:
252 // Session 3 start time.
253 $sessiontimes[2]['start'] = $timestamp;
254 break;
255 case 50:
256 // Session 3 end time.
257 $sessiontimes[2]['end'] = $timestamp;
258 break;
259 }
260
261 // User 1 to 5.
262 $user = rand(1, 5);
263
264 // Let's also include system messages as well. Give them to pop in 1-in-10 chance.
265 $issystem = rand(1, 10) == 10;
266
267 if ($issystem) {
268 $message = 'enter';
269 } else {
270 $message = 'Message ' . $i;
271 if (!isset($sessionusers[$session][$user])) {
272 $sessionusers[$session][$user] = 1;
273 } else {
274 $sessionusers[$session][$user]++;
275 }
276 }
277 $messages[] = (object)[
278 'id' => $i,
279 'chatid' => 1,
280 'userid' => $user,
281 'message' => $message,
282 'issystem' => $issystem,
283 'timestamp' => $timestamp,
284 ];
285
286 // Set the next timestamp.
287 if ($i == 10 || $i == 25) {
288 // New session.
289 $session++;
64818f40 290 $timestamp += CHAT_SESSION_GAP + 1;
70175dbe
JP
291 } else {
292 $timestamp += $gap;
293 }
294 }
295 // Reverse sort the messages so they're in descending order.
296 rsort($messages);
297
298 // Get chat sessions showing only complete ones.
299 $completesessions = chat_get_sessions($messages);
300 // Session 1 is incomplete, so there should only be 2 sessions when $showall is false.
301 $this->assertCount(2, $completesessions);
302
303 // Reverse sort sessions so they are in ascending order matching our expected session times and users.
304 $completesessions = array_reverse($completesessions);
305 foreach ($completesessions as $index => $session) {
306 // We increment index by 1 because the incomplete expected session (index=0) is not included.
307 $expectedindex = $index + 1;
308
309 // Check the session users.
310 $users = $sessionusers[$expectedindex];
311 $this->assertCount(count($users), $session->sessionusers);
312 // Check the message counts for each user in this session.
313 foreach ($users as $userid => $messagecount) {
314 $this->assertEquals($messagecount, $session->sessionusers[$userid]);
315 }
316
317 $sessionstart = $sessiontimes[$expectedindex]['start'];
318 $sessionend = $sessiontimes[$expectedindex]['end'];
319 $this->assertEquals($sessionstart, $session->sessionstart);
320 $this->assertEquals($sessionend, $session->sessionend);
321 }
322
323 // Get all the chat sessions.
324 $allsessions = chat_get_sessions($messages, true);
325 // When showall is true, we should get 3 sessions.
326 $this->assertCount(3, $allsessions);
327
328 // Reverse sort sessions so they are in ascending order matching our expected session times and users.
329 $allsessions = array_reverse($allsessions);
330 foreach ($allsessions as $index => $session) {
331 // Check the session users.
332 $users = $sessionusers[$index];
333 $this->assertCount(count($users), $session->sessionusers);
334 // Check the message counts for each user in this session.
335 foreach ($users as $userid => $messagecount) {
336 $this->assertEquals($messagecount, $session->sessionusers[$userid]);
337 }
338
339 $sessionstart = $sessiontimes[$index]['start'];
340 $sessionend = $sessiontimes[$index]['end'];
341 $this->assertEquals($sessionstart, $session->sessionstart);
342 $this->assertEquals($sessionend, $session->sessionend);
343 }
344 }
345
bea71d57
MN
346 /**
347 * Creates an action event.
348 *
349 * @param int $courseid
350 * @param int $instanceid The chat id.
351 * @param string $eventtype The event type. eg. ASSIGN_EVENT_TYPE_DUE.
e1cd93ce 352 * @return bool|calendar_event
bea71d57
MN
353 */
354 private function create_action_event($courseid, $instanceid, $eventtype) {
355 $event = new stdClass();
356 $event->name = 'Calendar event';
357 $event->modulename = 'chat';
358 $event->courseid = $courseid;
359 $event->instance = $instanceid;
360 $event->type = CALENDAR_EVENT_TYPE_ACTION;
361 $event->eventtype = $eventtype;
362 $event->timestart = time();
363
e1cd93ce 364 return calendar_event::create($event);
bea71d57
MN
365 }
366}