Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | 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
 * Tests for the Big Blue Button Instance.
18
 *
19
 * @package   mod_bigbluebuttonbn
20
 * @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
21
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
 
24
namespace mod_bigbluebuttonbn;
25
 
26
use advanced_testcase;
27
use moodle_exception;
28
 
29
/**
30
 * Tests for the Big Blue Button Instance.
31
 *
32
 * @package   mod_bigbluebuttonbn
33
 * @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
34
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 * @coversDefaultClass \mod_bigbluebuttonbn\instance
36
 */
37
class instance_test extends advanced_testcase {
38
 
39
    /**
40
     * Test get from
41
     *
42
     * @param string $function
43
     * @param string $field
44
     * @dataProvider get_from_location_provider
45
     * @covers ::get_from_instanceid
46
     * @covers ::get_from_cmid
47
     */
48
    public function test_get_from(string $function, string $field): void {
49
        $this->resetAfterTest();
50
 
51
        [
52
            'record' => $record,
53
        ] = $this->get_test_instance();
54
 
55
        $instance = call_user_func("mod_bigbluebuttonbn\instance::{$function}", $record->{$field});
56
 
57
        $this->assertInstanceOf(instance::class, $instance);
58
        $this->assertEquals($record->id, $instance->get_instance_id());
59
        $this->assertEquals($record->cmid, $instance->get_cm_id());
60
        $this->assertEquals($record->cmid, $instance->get_cm()->id);
61
    }
62
 
63
    /**
64
     * Get from location provider
65
     *
66
     * @return string[][]
67
     */
68
    public function get_from_location_provider(): array {
69
        return [
70
            ['get_from_instanceid', 'id'],
71
            ['get_from_cmid', 'cmid'],
72
        ];
73
    }
74
 
75
    /**
76
     * Get an instance from a cmid.
77
     * @covers ::get_from_cmid
78
     */
79
    public function test_get_from_cmid(): void {
80
        $this->resetAfterTest();
81
 
82
        [
83
            'record' => $record,
84
            'cm' => $cm,
85
        ] = $this->get_test_instance();
86
 
87
        $instance = instance::get_from_cmid($cm->id);
88
 
89
        $this->assertInstanceOf(instance::class, $instance);
90
        $this->assertEquals($record->id, $instance->get_instance_id());
91
        $this->assertEquals($cm->id, $instance->get_cm()->id);
92
    }
93
 
94
    /**
95
     * If the instance was not found, and exception should be thrown.
96
     * @covers ::get_from_cmid
97
     */
98
    public function test_get_from_cmid_not_found(): void {
99
        $this->assertNull(instance::get_from_cmid(100));
100
    }
101
 
102
    /**
103
     * If the instance was not found, and exception should be thrown.
104
     * @covers ::get_from_instanceid
105
     */
106
    public function test_get_from_instance_not_found(): void {
107
        $this->assertNull(instance::get_from_instanceid(100));
108
    }
109
 
110
    /**
111
     * Get from meeting id
112
     *
113
     * @covers ::get_from_meetingid
114
     */
115
    public function test_get_from_meetingid(): void {
116
        $this->resetAfterTest();
117
 
118
        [
119
            'record' => $record,
120
        ] = $this->get_test_instance();
121
 
122
        // The meetingid is confusingly made up of a meetingid field, courseid, instanceid, and groupid.
123
        $instance = instance::get_from_meetingid(sprintf(
124
            "%s-%s-%s",
125
            $record->meetingid,
126
            $record->course,
127
            $record->id
128
        ));
129
 
130
        $this->assertInstanceOf(instance::class, $instance);
131
        $this->assertEquals($record->id, $instance->get_instance_id());
132
        $this->assertEquals($record->cmid, $instance->get_cm_id());
133
        $this->assertEquals($record->cmid, $instance->get_cm()->id);
134
    }
135
 
136
    /**
137
     * Get the get_from_meetingid() function where the meetingid includes a groupid.
138
     *
139
     * @covers ::get_from_meetingid
140
     */
141
    public function test_get_from_meetingid_group(): void {
142
        $this->resetAfterTest();
143
 
144
        [
145
            'record' => $record,
146
            'course' => $course,
147
            'cm' => $cm,
148
        ] = $this->get_test_instance();
149
 
150
        $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
151
 
152
        $instance = instance::get_from_meetingid(
153
            sprintf("%s-%s-%s[0]", $record->meetingid, $record->course, $record->id)
154
        );
155
 
156
        $this->assertEquals($cm->instance, $instance->get_instance_id());
157
        $this->assertEquals($cm->id, $instance->get_cm_id());
158
    }
159
 
160
    /**
161
     * Test getting Meeting ID from log as Log field (meetingid) is the full meeting id (with courseid, and bigbluebuttonid).
162
     *
163
     * @covers ::get_from_meetingid
164
     */
165
    public function test_get_from_meetingid_from_log(): void {
166
        global $DB;
167
 
168
        $this->resetAfterTest();
169
        [
170
            'record' => $record,
171
            'course' => $course,
172
            'cm' => $cm,
173
        ] = $this->get_test_instance();
174
        $instance = instance::get_from_cmid($cm->id);
175
        $instance->set_group_id(1);
176
        logger::log_meeting_joined_event($instance, 1);
177
 
178
        // Get the meeting ID from the logged "join" event.
179
        $meetingid = $DB->get_field('bigbluebuttonbn_logs', 'meetingid', [
180
            'courseid' => $course->id,
181
            'bigbluebuttonbnid' => $instance->get_instance_id(),
182
            'log' => 'Join',
183
        ], MUST_EXIST);
184
 
185
        $retrievedinstance = instance::get_from_meetingid($meetingid);
186
        $this->assertEquals($cm->instance, $retrievedinstance->get_instance_id());
187
        $this->assertEquals($cm->id, $retrievedinstance->get_cm_id());
188
    }
189
 
190
    /**
191
     * Ensure that invalid meetingids throw an appropriate exception.
192
     *
193
     * @dataProvider invalid_meetingid_provider
194
     * @param string $meetingid
195
     * @covers ::get_from_meetingid
196
     */
197
    public function test_get_from_meetingid_invalid(string $meetingid): void {
198
        $this->expectException(moodle_exception::class);
199
        instance::get_from_meetingid($meetingid);
200
    }
201
 
202
    /**
203
     * Provide invalid meeting examples
204
     *
205
     * @return \string[][]
206
     */
207
    public function invalid_meetingid_provider(): array {
208
        // Meeting IDs are in the formats:
209
        // - <meetingid[string]>-<courseid[number]>-<instanceid[number]>
210
        // - <meetingid[string]>-<courseid[number]>-<instanceid[number]>[<groupid[number]>]
211
        // Note: deducing the group from meeting id will soon be deprecated.
212
        return [
213
            'Non-numeric instanceid' => ['aaa-123-aaa'],
214
        ];
215
    }
216
 
217
    /**
218
     * Test the get_all_instances_in_course function.
219
     *
220
     * @covers ::get_all_instances_in_course
221
     */
222
    public function test_get_all_instances_in_course(): void {
223
        $this->resetAfterTest();
224
 
225
        $course = $this->getDataGenerator()->create_course();
226
        $records = [];
227
        for ($i = 0; $i < 5; $i++) {
228
            $this->getDataGenerator()->create_module('bigbluebuttonbn', [
229
                'course' => $course->id,
230
            ]);
231
        }
232
 
233
        $instances = instance::get_all_instances_in_course($course->id);
234
        $this->assertCount(5, $instances);
235
        foreach ($instances as $instance) {
236
            $this->assertInstanceOf(instance::class, $instance);
237
        }
238
    }
239
 
240
    /**
241
     * Get test instance from data
242
     *
243
     * @param array $data
244
     * @return array
245
     */
246
    protected function get_test_instance(array $data = []): array {
247
        $course = $this->getDataGenerator()->create_course();
248
        $record = $this->getDataGenerator()->create_module('bigbluebuttonbn', array_merge([
249
            'course' => $course->id,
250
        ], $data));
251
        $cm = get_fast_modinfo($course)->instances['bigbluebuttonbn'][$record->id];
252
 
253
        return [
254
            'course' => $course,
255
            'record' => $record,
256
            'cm' => $cm,
257
        ];
258
    }
259
 
260
    /**
261
     * Test the get_meeting_id function for a meeting configured for a group.
262
     *
263
     * @covers ::get_meeting_id
264
     */
265
    public function test_get_meeting_id_with_groups(): void {
266
        $this->resetAfterTest();
267
 
268
        [
269
            'record' => $record,
270
            'course' => $course,
271
        ] = $this->get_test_instance();
272
 
273
        $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
274
 
275
        $instance = instance::get_from_instanceid($record->id);
276
 
277
        // No group.
278
        $this->assertEquals(
279
            sprintf("%s-%s-%s[0]", $record->meetingid, $record->course, $record->id),
280
            $instance->get_meeting_id(0)
281
        );
282
 
283
        // Specified group.
284
        $this->assertEquals(
285
            sprintf("%s-%s-%s[%d]", $record->meetingid, $record->course, $record->id, $group->id),
286
            $instance->get_meeting_id($group->id)
287
        );
288
    }
289
 
290
    /**
291
     * Test the get_meeting_id function for a meeting configured for a group.
292
     *
293
     * @covers ::get_meeting_id
294
     */
295
    public function test_get_meeting_id_without_groups(): void {
296
        $this->resetAfterTest();
297
 
298
        [
299
            'record' => $record,
300
            'course' => $course,
301
        ] = $this->get_test_instance();
302
 
303
        $instance = instance::get_from_instanceid($record->id);
304
 
305
        // No group.
306
        $this->assertEquals(
307
            sprintf("%s-%s-%s[0]", $record->meetingid, $record->course, $record->id),
308
            $instance->get_meeting_id(null)
309
        );
310
    }
311
 
312
    /**
313
     * Data provider to check the various room_available scenarios'
314
     *
315
     * @return array
316
     */
317
    public function is_currently_open_provider(): array {
318
        return [
319
            'No opening or closing time set: Is open' => [null, null, true],
320
            'Opening time set in the past, no closing: Is open' => [-DAYSECS, null, true],
321
            'Opening time set in the future, no closing: Is closed' => [+DAYSECS, null, false],
322
            'Closing time set in the past, no opening: Is closed' => [null, -DAYSECS, false],
323
            'Closing time set in the future, no opening: Is open' => [null, +DAYSECS, true],
324
            'Opening and closing in the past: Is closed' => [-WEEKSECS, -DAYSECS, false],
325
            'Opening and closing in the future: Is closed' => [+DAYSECS, +WEEKSECS, false],
326
            'Opening in the past, Closing in the future: Is open' => [-DAYSECS, +DAYSECS, true],
327
        ];
328
    }
329
 
330
    /**
331
     * Check instance currently open
332
     *
333
     * @dataProvider is_currently_open_provider
334
     * @param null|int $openingtime
335
     * @param null|int $closingtime
336
     * @param bool $expected
337
     * @covers ::is_currently_open
338
     */
339
    public function test_is_currently_open(?int $openingtime, ?int $closingtime, bool $expected): void {
340
        $stub = $this->getMockBuilder(instance::class)
341
            ->onlyMethods(['get_instance_var'])
342
            ->disableOriginalConstructor()
343
            ->getMock();
344
 
345
        if ($openingtime) {
346
            $openingtime = $openingtime + time();
347
        }
348
 
349
        if ($closingtime) {
350
            $closingtime = $closingtime + time();
351
        }
352
 
353
        $stub->method('get_instance_var')
354
            ->willReturnCallback(function($var) use ($openingtime, $closingtime) {
355
                if ($var === 'openingtime') {
356
                    return $openingtime;
357
                }
358
 
359
                return $closingtime;
360
            });
361
        $this->assertEquals($expected, $stub->is_currently_open());
362
    }
363
 
364
    /**
365
     * Ensure that the user_must_wait_to_join function works as expectd.
366
     *
367
     * @dataProvider user_must_wait_to_join_provider
368
     * @param bool $isadmin
369
     * @param bool $ismoderator
370
     * @param bool $haswaitingroom
371
     * @param bool $expected
372
     * @covers ::user_must_wait_to_join
373
     */
374
    public function test_user_must_wait_to_join(bool $isadmin, bool $ismoderator, bool $haswaitingroom, bool $expected): void {
375
        $stub = $this->getMockBuilder(instance::class)
376
            ->setMethods([
377
                'get_instance_var',
378
                'is_admin',
379
                'is_moderator',
380
            ])
381
            ->disableOriginalConstructor()
382
            ->getMock();
383
 
384
        $stub->method('is_admin')->willReturn($isadmin);
385
        $stub->method('is_moderator')->willReturn($ismoderator);
386
        $stub->method('get_instance_var')->willReturn($haswaitingroom);
387
 
388
        $this->assertEquals($expected, $stub->user_must_wait_to_join());
389
    }
390
 
391
    /**
392
     * Data provider for the user_must_wait_to_join function.
393
     *
394
     * @return array
395
     */
396
    public function user_must_wait_to_join_provider(): array {
397
        return [
398
            'Admins must never wait to join (waiting disabled)' => [true, false, false, false],
399
            'Admins must never wait to join (waiting enabled)' => [true, false, true, false],
400
            'Moderators must never wait to join (waiting disabled)' => [false, true, false, false],
401
            'Moderators must never wait to join (waiting enabled)' => [false, true, true, false],
402
            'Other users must wait to join if waiting enabled' => [false, false, true, true],
403
            'Other users cannot wait to join if waiting disabled' => [false, false, false, false],
404
        ];
405
    }
406
 
407
    /**
408
     * Ensure that the does_current_user_count_towards_user_limit function works as expectd.
409
     *
410
     * @dataProvider does_current_user_count_towards_user_limit_provider
411
     * @param bool $isadmin
412
     * @param bool $ismoderator
413
     * @param bool $expected
414
     * @covers ::does_current_user_count_towards_user_limit
415
     */
416
    public function test_does_current_user_count_towards_user_limit(
417
        bool $isadmin,
418
        bool $ismoderator,
419
        bool $expected
420
    ): void {
421
        $stub = $this->getMockBuilder(instance::class)
422
            ->setMethods([
423
                'is_admin',
424
                'is_moderator',
425
            ])
426
            ->disableOriginalConstructor()
427
            ->getMock();
428
 
429
        $stub->method('is_admin')->willReturn($isadmin);
430
        $stub->method('is_moderator')->willReturn($ismoderator);
431
 
432
        $this->assertEquals($expected, $stub->does_current_user_count_towards_user_limit());
433
    }
434
 
435
    /**
436
     * Data provider for the does_current_user_count_towards_user_limit function.
437
     *
438
     * @return array
439
     */
440
    public function does_current_user_count_towards_user_limit_provider(): array {
441
        return [
442
            'Admin does not count' => [true, false, false],
443
            'Moderator does not count' => [false, true, false],
444
            'Other users do count' => [false, false, true],
445
        ];
446
    }
447
 
448
    /**
449
     * Ensure that the does_current_user_count_towards_user_limit function works as expectd.
450
     *
451
     * @dataProvider get_current_user_password_provider
452
     * @param bool $isadmin
453
     * @param bool $ismoderator
454
     * @param bool $expectedmodpassword
455
     * @covers ::get_current_user_password
456
     */
457
    public function test_get_current_user_password(bool $isadmin, bool $ismoderator, bool $expectedmodpassword): void {
458
        $stub = $this->getMockBuilder(instance::class)
459
            ->setMethods([
460
                'is_admin',
461
                'is_moderator',
462
                'get_moderator_password',
463
                'get_viewer_password',
464
            ])
465
            ->disableOriginalConstructor()
466
            ->getMock();
467
 
468
        $stub->method('is_admin')->willReturn($isadmin);
469
        $stub->method('is_moderator')->willReturn($ismoderator);
470
        $stub->method('get_moderator_password')->willReturn('Moderator Password');
471
        $stub->method('get_viewer_password')->willReturn('Viewer Password');
472
 
473
        if ($expectedmodpassword) {
474
            $this->assertEquals('Moderator Password', $stub->get_current_user_password());
475
        } else {
476
            $this->assertEquals('Viewer Password', $stub->get_current_user_password());
477
        }
478
    }
479
 
480
    /**
481
     * Data provider for the get_current_user_password function.
482
     *
483
     * @return array
484
     */
485
    public function get_current_user_password_provider(): array {
486
        return [
487
            'Admin is a moderator' => [true, false, true],
488
            'Moderator is a moderator' => [false, true, true],
489
            'Others are a viewer' => [false, false, false],
490
        ];
491
    }
492
 
493
    /**
494
     * Ensure that the get_current_user_role function works as expected.
495
     *
496
     * @dataProvider get_current_user_role_provider
497
     * @param bool $isadmin
498
     * @param bool $ismoderator
499
     * @param bool $expectedmodrole
500
     * @covers ::get_current_user_role
501
     */
502
    public function test_get_current_user_role(bool $isadmin, bool $ismoderator, bool $expectedmodrole): void {
503
        $stub = $this->getMockBuilder(instance::class)
504
            ->setMethods([
505
                'is_admin',
506
                'is_moderator',
507
            ])
508
            ->disableOriginalConstructor()
509
            ->getMock();
510
 
511
        $stub->method('is_admin')->willReturn($isadmin);
512
        $stub->method('is_moderator')->willReturn($ismoderator);
513
 
514
        if ($expectedmodrole) {
515
            $this->assertEquals('MODERATOR', $stub->get_current_user_role());
516
        } else {
517
            $this->assertEquals('VIEWER', $stub->get_current_user_role());
518
        }
519
    }
520
 
521
    /**
522
     * Data provider for the get_current_user_role function.
523
     *
524
     * @return array
525
     */
526
    public function get_current_user_role_provider(): array {
527
        return [
528
            'Admin is a moderator' => [true, false, true],
529
            'Moderator is a moderator' => [false, true, true],
530
            'Others are a viewer' => [false, false, false],
531
        ];
532
    }
533
 
534
    /**
535
     * Tests for the allow_recording_start_stop function.
536
     *
537
     * @dataProvider allow_recording_start_stop_provider
538
     * @param bool $isrecorded
539
     * @param bool $showbuttons
540
     * @param bool $expected
541
     * @covers ::allow_recording_start_stop
542
     */
543
    public function test_allow_recording_start_stop(
544
        bool $isrecorded,
545
        bool $showbuttons,
546
        bool $expected
547
    ): void {
548
        $stub = $this->getMockBuilder(instance::class)
549
            ->setMethods([
550
                'is_recorded',
551
                'should_show_recording_button',
552
            ])
553
            ->disableOriginalConstructor()
554
            ->getMock();
555
 
556
        $stub->method('is_recorded')->willReturn($isrecorded);
557
        $stub->method('should_show_recording_button')->willReturn($showbuttons);
558
 
559
        $this->assertEquals($expected, $stub->allow_recording_start_stop());
560
    }
561
 
562
    /**
563
     * Data provider for the allow_recording_start_stop function.
564
     *
565
     * @return array
566
     */
567
    public function allow_recording_start_stop_provider(): array {
568
        return [
569
            'Meeting is not recorded: No start/stop' => [false, false, false],
570
            'Meeting recorded, Buttons shown: Allow' => [true, true, true],
571
            'Meeting recorded, Buttons not shown: Deny' => [true, false, false],
572
        ];
573
    }
574
 
575
 
576
    /**
577
     * Test get user id (guest or current user)
578
     * @covers \mod_bigbluebuttonbn\instance::get_user_id
579
     */
580
    public function test_get_user_id(): void {
581
        $this->resetAfterTest();
582
        $this->setUser(null);
583
        ['record' => $record ] = $this->get_test_instance();
584
        $instance = instance::get_from_instanceid($record->id);
585
        $this->assertEquals(0, $instance->get_user_id());
586
        $user = $this->getDataGenerator()->create_user();
587
        $this->setUser($user);
588
        $this->assertEquals($user->id, $instance->get_user_id());
589
    }
590
 
591
    /**
592
     * Test guest access URL
593
     *
594
     * @covers ::get_guest_access_url
595
     */
596
    public function test_get_guest_access_url() {
597
        global $CFG;
598
        $this->resetAfterTest();
599
        ['record' => $record ] = $this->get_test_instance(['guestallowed' => true]);
600
        $CFG->bigbluebuttonbn['guestaccess_enabled'] = 1;
601
        $instance = instance::get_from_instanceid($record->id);
602
        $this->assertNotEmpty($instance->get_guest_access_url());
603
    }
604
 
605
    /**
606
     * Test guest allowed flag
607
     *
608
     * @covers ::is_guest_allowed
609
     */
610
    public function test_is_guest_allowed() {
611
        global $CFG;
612
        $this->resetAfterTest();
613
        ['record' => $record ] = $this->get_test_instance(['guestallowed' => true]);
614
        $CFG->bigbluebuttonbn['guestaccess_enabled'] = 1;
615
        $instance = instance::get_from_instanceid($record->id);
616
        $this->assertTrue($instance->is_guest_allowed());
617
        $CFG->bigbluebuttonbn['guestaccess_enabled'] = 0;
618
        $this->assertFalse($instance->is_guest_allowed());
619
    }
620
 
621
    /**
622
     * Test private method get_instance_info_retriever
623
     *
624
     * @covers ::get_instance_info_retriever
625
     */
626
    public function test_get_instance_info_retriever() {
627
        $this->resetAfterTest();
628
        [
629
            'record' => $record,
630
            'cm' => $cm,
631
        ] = $this->get_test_instance();
632
        $instance = instance::get_from_instanceid($record->id);
633
        $instancereflection = new \ReflectionClass($instance);
634
        $getinstanceinforetriever = $instancereflection->getMethod('get_instance_info_retriever');
635
        $this->assertInstanceOf('\mod_bigbluebuttonbn\instance',
636
            $getinstanceinforetriever->invoke($instance, $record->id, instance::IDTYPE_INSTANCEID));
637
        $this->assertEquals($cm->id, $instance->get_cm_id());
638
    }
639
 
640
    /**
641
     * Test guest access password
642
     *
643
     * @covers ::get_guest_access_password
644
     */
645
    public function get_guest_access_password() {
646
        global $CFG;
647
        $this->resetAfterTest();
648
        ['record' => $record ] = $this->get_test_instance(['guestallowed' => true]);
649
        $CFG->bigbluebuttonbn['guestaccess_enabled'] = 1;
650
        $instance = instance::get_from_instanceid($record->id);
651
        $this->assertNotEmpty($instance->get_guest_access_password());
652
    }
653
}