Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
namespace mod_chat;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
/**
30
 * Class containing unit tests for mod/chat/lib.php.
31
 *
32
 * @package mod_chat
33
 * @category test
34
 * @copyright 2017 Mark Nelson <markn@moodle.com>
35
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36
 */
37
class lib_test extends \advanced_testcase {
38
 
39
    public function setUp(): void {
40
        $this->resetAfterTest();
41
 
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);
45
    }
46
 
47
    /*
48
     * The chat's event should not be shown to a user when the user cannot view the chat at all.
49
     */
11 efrain 50
    public function test_chat_core_calendar_provide_event_action_in_hidden_section(): void {
1 efrain 51
        global $CFG;
52
 
53
        $this->setAdminUser();
54
 
55
        // Create a course.
56
        $course = $this->getDataGenerator()->create_course();
57
 
58
        // Create a student.
59
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
60
 
61
        // Create a chat.
62
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
63
                'chattime' => usergetmidnight(time())));
64
 
65
        // Create a calendar event.
66
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
67
 
68
        // Set sections 0 as hidden.
69
        set_section_visible($course->id, 0, 0);
70
 
71
        // Now, log out.
72
        $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
73
        $this->setUser();
74
 
75
        // Create an action factory.
76
        $factory = new \core_calendar\action_factory();
77
 
78
        // Decorate action event for the student.
79
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
80
 
81
        // Confirm the event is not shown at all.
82
        $this->assertNull($actionevent);
83
    }
84
 
85
    /*
86
     * The chat's event should not be shown to a user who does not have permission to view the chat at all.
87
     */
11 efrain 88
    public function test_chat_core_calendar_provide_event_action_for_non_user(): void {
1 efrain 89
        global $CFG;
90
 
91
        $this->setAdminUser();
92
 
93
        // Create a course.
94
        $course = $this->getDataGenerator()->create_course();
95
 
96
        // Create a chat.
97
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
98
                'chattime' => usergetmidnight(time())));
99
 
100
        // Create a calendar event.
101
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
102
 
103
        // Now, log out.
104
        $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
105
        $this->setUser();
106
 
107
        // Create an action factory.
108
        $factory = new \core_calendar\action_factory();
109
 
110
        // Decorate action event.
111
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
112
 
113
        // Confirm the event is not shown at all.
114
        $this->assertNull($actionevent);
115
    }
116
 
11 efrain 117
    public function test_chat_core_calendar_provide_event_action_chattime_event_yesterday(): void {
1 efrain 118
        $this->setAdminUser();
119
 
120
        // Create a course.
121
        $course = $this->getDataGenerator()->create_course();
122
 
123
        // Create a chat.
124
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
125
            'chattime' => time() - DAYSECS));
126
 
127
        // Create a calendar event.
128
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
129
 
130
        // Create an action factory.
131
        $factory = new \core_calendar\action_factory();
132
 
133
        // Decorate action event.
134
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
135
 
136
        // Confirm the event is not shown at all.
137
        $this->assertNull($actionevent);
138
    }
139
 
11 efrain 140
    public function test_chat_core_calendar_provide_event_action_chattime_event_yesterday_for_user(): void {
1 efrain 141
        global $CFG;
142
 
143
        $this->setAdminUser();
144
 
145
        // Create a course.
146
        $course = $this->getDataGenerator()->create_course();
147
 
148
        // Enrol a student in the course.
149
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
150
 
151
        // Create a chat.
152
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
153
                'chattime' => time() - DAYSECS));
154
 
155
        // Create a calendar event.
156
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
157
 
158
        // Now, log out.
159
        $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
160
        $this->setUser();
161
 
162
        // Create an action factory.
163
        $factory = new \core_calendar\action_factory();
164
 
165
        // Decorate action event for the student.
166
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
167
 
168
        // Confirm the event is not shown at all.
169
        $this->assertNull($actionevent);
170
    }
171
 
11 efrain 172
    public function test_chat_core_calendar_provide_event_action_chattime_event_today(): void {
1 efrain 173
        $this->setAdminUser();
174
 
175
        // Create a course.
176
        $course = $this->getDataGenerator()->create_course();
177
 
178
        // Create a chat.
179
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
180
            'chattime' => usergetmidnight(time())));
181
 
182
        // Create a calendar event.
183
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
184
 
185
        // Create an action factory.
186
        $factory = new \core_calendar\action_factory();
187
 
188
        // Decorate action event.
189
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
190
 
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());
197
    }
198
 
11 efrain 199
    public function test_chat_core_calendar_provide_event_action_chattime_event_today_for_user(): void {
1 efrain 200
        global $CFG;
201
 
202
        $this->setAdminUser();
203
 
204
        // Create a course.
205
        $course = $this->getDataGenerator()->create_course();
206
 
207
        // Enrol a student in the course.
208
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
209
 
210
        // Create a chat.
211
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
212
                'chattime' => usergetmidnight(time())));
213
 
214
        // Create a calendar event.
215
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
216
 
217
        // Now, log out.
218
        $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
219
        $this->setUser();
220
 
221
        // Create an action factory.
222
        $factory = new \core_calendar\action_factory();
223
 
224
        // Decorate action event for the student.
225
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
226
 
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());
233
    }
234
 
11 efrain 235
    public function test_chat_core_calendar_provide_event_action_chattime_event_tonight(): void {
1 efrain 236
        $this->setAdminUser();
237
 
238
        // Create a course.
239
        $course = $this->getDataGenerator()->create_course();
240
 
241
        // Create a chat.
242
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
243
            'chattime' => usergetmidnight(time()) + (23 * HOURSECS)));
244
 
245
        // Create a calendar event.
246
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
247
 
248
        // Create an action factory.
249
        $factory = new \core_calendar\action_factory();
250
 
251
        // Decorate action event.
252
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
253
 
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());
260
    }
261
 
11 efrain 262
    public function test_chat_core_calendar_provide_event_action_chattime_event_tonight_for_user(): void {
1 efrain 263
        global $CFG;
264
 
265
        $this->setAdminUser();
266
 
267
        // Create a course.
268
        $course = $this->getDataGenerator()->create_course();
269
 
270
        // Enrol a student in the course.
271
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
272
 
273
        // Create a chat.
274
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
275
                'chattime' => usergetmidnight(time()) + (23 * HOURSECS)));
276
 
277
        // Create a calendar event.
278
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
279
 
280
        // Now, log out.
281
        $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
282
        $this->setUser();
283
 
284
        // Create an action factory.
285
        $factory = new \core_calendar\action_factory();
286
 
287
        // Decorate action event for the student.
288
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
289
 
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());
296
    }
297
 
11 efrain 298
    public function test_chat_core_calendar_provide_event_action_chattime_event_tomorrow(): void {
1 efrain 299
        $this->setAdminUser();
300
 
301
        // Create a course.
302
        $course = $this->getDataGenerator()->create_course();
303
 
304
        // Create a chat.
305
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
306
            'chattime' => time() + DAYSECS));
307
 
308
        // Create a calendar event.
309
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
310
 
311
        // Create an action factory.
312
        $factory = new \core_calendar\action_factory();
313
 
314
        // Decorate action event.
315
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
316
 
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());
323
    }
324
 
11 efrain 325
    public function test_chat_core_calendar_provide_event_action_chattime_event_tomorrow_for_user(): void {
1 efrain 326
        global $CFG;
327
 
328
        $this->setAdminUser();
329
 
330
        // Create a course.
331
        $course = $this->getDataGenerator()->create_course();
332
 
333
        // Enrol a student in the course.
334
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
335
 
336
        // Create a chat.
337
        $chat = $this->getDataGenerator()->create_module('chat', array('course' => $course->id,
338
                'chattime' => time() + DAYSECS));
339
 
340
        // Create a calendar event.
341
        $event = $this->create_action_event($course->id, $chat->id, CHAT_EVENT_TYPE_CHATTIME);
342
 
343
        // Now, log out.
344
        $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
345
        $this->setUser();
346
 
347
        // Create an action factory.
348
        $factory = new \core_calendar\action_factory();
349
 
350
        // Decorate action event for the student.
351
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
352
 
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());
359
    }
360
 
11 efrain 361
    public function test_chat_core_calendar_provide_event_action_chattime_event_different_timezones(): void {
1 efrain 362
        global $CFG;
363
 
364
        $this->setAdminUser();
365
 
366
        // Create a course.
367
        $course = $this->getDataGenerator()->create_course();
368
 
369
        $hour = gmdate('H');
370
 
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).
374
        if ($hour < 10) {
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.
380
        } else {
381
            $timezone1 = 'Pacific/Kiritimati';  // GMT +14:00.
382
            $timezone2 = 'UTC';                 // GMT.
383
        }
384
 
385
        $this->setTimezone($timezone2);
386
 
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]);
390
 
391
        // Create a chat.
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.
395
 
396
        // Create a chat.
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.
400
 
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);
404
 
405
        // Now, log out.
406
        $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users have mod/chat:view capability by default.
407
        $this->setUser();
408
 
409
        // Create an action factory.
410
        $factory = new \core_calendar\action_factory();
411
 
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);
417
 
418
        // Confirm event1 is not shown to student1 at all.
419
        $this->assertNull($actionevent11, 'Failed for UTC time ' . gmdate('H:i'));
420
 
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());
427
 
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());
434
 
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());
441
    }
442
 
443
    /**
444
     * Test for chat_get_sessions().
445
     */
11 efrain 446
    public function test_chat_get_sessions(): void {
1 efrain 447
        global $DB;
448
 
449
        $this->resetAfterTest();
450
 
451
        $generator = $this->getDataGenerator();
452
 
453
        // Setup test data.
454
        $this->setAdminUser();
455
        $course = $generator->create_course();
456
        $chat = $generator->create_module('chat', ['course' => $course->id]);
457
 
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);
463
 
464
        // Login as user 1.
465
        $this->setUser($user1);
466
        $chatsid = chat_login_user($chat->id, 'ajax', 0, $course);
467
        $chatuser = $DB->get_record('chat_users', ['sid' => $chatsid]);
468
 
469
        // Get the messages for this chat session.
470
        $messages = chat_get_session_messages($chat->id, false, 0, 0, 'timestamp DESC');
471
 
472
        // We should have just 1 system (enter) messages.
473
        $this->assertCount(1, $messages);
474
 
475
        // This is when the session starts (when the first message - enter - has been sent).
476
        $sessionstart = reset($messages)->timestamp;
477
 
478
        // Send some messages.
479
        chat_send_chatmessage($chatuser, 'hello!');
480
        chat_send_chatmessage($chatuser, 'bye bye!');
481
 
482
        // Login as user 2.
483
        $this->setUser($user2);
484
        $chatsid = chat_login_user($chat->id, 'ajax', 0, $course);
485
        $chatuser = $DB->get_record('chat_users', ['sid' => $chatsid]);
486
 
487
        // Send a message and take note of this message ID.
488
        $messageid = chat_send_chatmessage($chatuser, 'greetings!');
489
 
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]);
492
 
493
        // Get the messages for this chat session.
494
        $messages = chat_get_session_messages($chat->id, false, 0, 0, 'timestamp DESC');
495
 
496
        // We should have 3 user and 2 system (enter) messages.
497
        $this->assertCount(5, $messages);
498
 
499
        // Fetch the chat sessions from the messages we retrieved.
500
        $sessions = chat_get_sessions($messages, true);
501
 
502
        // There should be only one session.
503
        $this->assertCount(1, $sessions);
504
 
505
        // Get this session.
506
        $session = reset($sessions);
507
 
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);
513
    }
514
 
515
    /**
516
     * Test for chat_get_sessions with messages belonging to multiple sessions.
517
     */
11 efrain 518
    public function test_chat_get_sessions_multiple(): void {
1 efrain 519
        $messages = [];
520
        $gap = 5; // 5 secs.
521
 
522
        $now = time();
523
        $timestamp = $now;
524
 
525
        // Messages belonging to 3 sessions. Session 1 has 10 messages, 2 has 15, 3 has 25.
526
        $sessionusers = [];
527
        $sessiontimes = [];
528
        $session = 0; // Incomplete session.
529
        for ($i = 1; $i <= 50; $i++) {
530
            // Take note of expected session times as we go through.
531
            switch ($i) {
532
                case 1:
533
                    // Session 1 start time.
534
                    $sessiontimes[0]['start'] = $timestamp;
535
                    break;
536
                case 10:
537
                    // Session 1 end time.
538
                    $sessiontimes[0]['end'] = $timestamp;
539
                    break;
540
                case 11:
541
                    // Session 2 start time.
542
                    $sessiontimes[1]['start'] = $timestamp;
543
                    break;
544
                case 25:
545
                    // Session 2 end time.
546
                    $sessiontimes[1]['end'] = $timestamp;
547
                    break;
548
                case 26:
549
                    // Session 3 start time.
550
                    $sessiontimes[2]['start'] = $timestamp;
551
                    break;
552
                case 50:
553
                    // Session 3 end time.
554
                    $sessiontimes[2]['end'] = $timestamp;
555
                    break;
556
            }
557
 
558
            // User 1 to 5.
559
            $user = rand(1, 5);
560
 
561
            // Let's also include system messages as well. Give them to pop in 1-in-10 chance.
562
            $issystem = rand(1, 10) == 10;
563
 
564
            if ($issystem) {
565
                $message = 'enter';
566
            } else {
567
                $message = 'Message ' . $i;
568
                if (!isset($sessionusers[$session][$user])) {
569
                    $sessionusers[$session][$user] = 1;
570
                } else {
571
                    $sessionusers[$session][$user]++;
572
                }
573
            }
574
            $messages[] = (object)[
575
                'id' => $i,
576
                'chatid' => 1,
577
                'userid' => $user,
578
                'message' => $message,
579
                'issystem' => $issystem,
580
                'timestamp' => $timestamp,
581
            ];
582
 
583
            // Set the next timestamp.
584
            if ($i == 10 || $i == 25) {
585
                // New session.
586
                $session++;
587
                $timestamp += CHAT_SESSION_GAP + 1;
588
            } else {
589
                $timestamp += $gap;
590
            }
591
        }
592
        // Reverse sort the messages so they're in descending order.
593
        rsort($messages);
594
 
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);
599
 
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;
605
 
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]);
612
            }
613
 
614
            $sessionstart = $sessiontimes[$expectedindex]['start'];
615
            $sessionend = $sessiontimes[$expectedindex]['end'];
616
            $this->assertEquals($sessionstart, $session->sessionstart);
617
            $this->assertEquals($sessionend, $session->sessionend);
618
        }
619
 
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);
624
 
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]);
634
            }
635
 
636
            $sessionstart = $sessiontimes[$index]['start'];
637
            $sessionend = $sessiontimes[$index]['end'];
638
            $this->assertEquals($sessionstart, $session->sessionstart);
639
            $this->assertEquals($sessionend, $session->sessionend);
640
        }
641
    }
642
 
11 efrain 643
    public function test_chat_core_calendar_provide_event_action_already_completed(): void {
1 efrain 644
        set_config('enablecompletion', 1);
645
        $this->setAdminUser();
646
 
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));
651
 
652
        // Get some additional data.
653
        $cm = get_coursemodule_from_instance('chat', $chat->id);
654
 
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);
658
 
659
        // Mark the activity as completed.
660
        $completion = new \completion_info($course);
661
        $completion->set_module_viewed($cm);
662
 
663
        // Create an action factory.
664
        $factory = new \core_calendar\action_factory();
665
 
666
        // Decorate action event.
667
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory);
668
 
669
        // Ensure result was null.
670
        $this->assertNull($actionevent);
671
    }
672
 
11 efrain 673
    public function test_chat_core_calendar_provide_event_action_already_completed_for_user(): void {
1 efrain 674
        set_config('enablecompletion', 1);
675
        $this->setAdminUser();
676
 
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));
681
 
682
        // Enrol a student in the course.
683
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
684
 
685
        // Get some additional data.
686
        $cm = get_coursemodule_from_instance('chat', $chat->id);
687
 
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);
691
 
692
        // Mark the activity as completed for the student.
693
        $completion = new \completion_info($course);
694
        $completion->set_module_viewed($cm, $student->id);
695
 
696
        // Create an action factory.
697
        $factory = new \core_calendar\action_factory();
698
 
699
        // Decorate action event for the student.
700
        $actionevent = mod_chat_core_calendar_provide_event_action($event, $factory, $student->id);
701
 
702
        // Ensure result was null.
703
        $this->assertNull($actionevent);
704
    }
705
 
706
    /**
707
     * Creates an action event.
708
     *
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
713
     */
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();
723
 
724
        return \calendar_event::create($event);
725
    }
726
 
727
    /**
728
     * A user who does not have capabilities to add events to the calendar should be able to create an chat.
729
     */
11 efrain 730
    public function test_creation_with_no_calendar_capabilities(): void {
1 efrain 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);
741
        $params = array(
742
            'course' => $course->id,
743
            'chattime' => time() + 500,
744
        );
745
        $generator->create_instance($params);
746
    }
747
}