Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 400 and 401]

   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   * BBB Library tests class.
  19   *
  20   * @package   mod_bigbluebuttonbn
  21   * @copyright 2018 - present, Blindside Networks Inc
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   * @author    Laurent David (laurent@call-learning.fr)
  24   */
  25  
  26  namespace mod_bigbluebuttonbn;
  27  
  28  use calendar_event;
  29  use context_module;
  30  use mod_bigbluebuttonbn\test\testcase_helper_trait;
  31  use mod_bigbluebuttonbn_mod_form;
  32  use MoodleQuickForm;
  33  use navigation_node;
  34  use ReflectionClass;
  35  use stdClass;
  36  
  37  defined('MOODLE_INTERNAL') || die();
  38  global $CFG;
  39  require_once($CFG->dirroot . '/mod/bigbluebuttonbn/lib.php');
  40  
  41  /**
  42   * BBB Library tests class.
  43   *
  44   * @package   mod_bigbluebuttonbn
  45   * @copyright 2018 - present, Blindside Networks Inc
  46   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  47   * @author    Laurent David (laurent@call-learning.fr)
  48   */
  49  class lib_test extends \advanced_testcase {
  50      use testcase_helper_trait;
  51  
  52      /**
  53       * Check support
  54       *
  55       * @covers ::bigbluebuttonbn_supports
  56       */
  57      public function test_bigbluebuttonbn_supports() {
  58          $this->resetAfterTest();
  59          $this->assertTrue(bigbluebuttonbn_supports(FEATURE_IDNUMBER));
  60          $this->assertTrue(bigbluebuttonbn_supports(FEATURE_MOD_INTRO));
  61          $this->assertFalse(bigbluebuttonbn_supports(FEATURE_GRADE_HAS_GRADE));
  62      }
  63  
  64      /**
  65       * Check add instance
  66       *
  67       * @covers ::bigbluebuttonbn_add_instance
  68       */
  69      public function test_bigbluebuttonbn_add_instance() {
  70          $this->resetAfterTest();
  71          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
  72          $bbformdata = $this->get_form_data_from_instance($bbactivity);
  73          $id = bigbluebuttonbn_add_instance($bbformdata);
  74          $this->assertNotNull($id);
  75      }
  76  
  77      /**
  78       * Check update instance
  79       *
  80       * @covers ::bigbluebuttonbn_update_instance
  81       */
  82      public function test_bigbluebuttonbn_update_instance() {
  83          $this->resetAfterTest();
  84          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
  85          $bbformdata = $this->get_form_data_from_instance($bbactivity);
  86          $result = bigbluebuttonbn_update_instance($bbformdata);
  87          $this->assertTrue($result);
  88      }
  89  
  90      /**
  91       * Check delete instance
  92       *
  93       * @covers ::bigbluebuttonbn_delete_instance
  94       */
  95      public function test_bigbluebuttonbn_delete_instance() {
  96          $this->resetAfterTest();
  97          $this->initialise_mock_server();
  98          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
  99          $result = bigbluebuttonbn_delete_instance($bbactivity->id);
 100          $this->assertTrue($result);
 101      }
 102  
 103      /**
 104       * Check delete instance
 105       *
 106       * @covers ::bigbluebuttonbn_delete_instance
 107       */
 108      public function test_bigbluebuttonbn_delete_instance_with_running_meeting() {
 109          $this->resetAfterTest();
 110          $this->initialise_mock_server();
 111          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 112          $bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
 113          $instance = instance::get_from_instanceid($bbactivity->id);
 114          // Run the meeting.
 115          $bbbgenerator->create_meeting([
 116              'instanceid' => $instance->get_instance_id(),
 117              'groupid' => $instance->get_group_id(),
 118          ]);
 119          $meeting = new meeting($instance);
 120          $meeting->update_cache();
 121          $this->assertTrue($meeting->is_running());
 122          $result = bigbluebuttonbn_delete_instance($bbactivity->id);
 123          $this->assertTrue($result);
 124          $meeting->update_cache();
 125          $this->assertFalse($meeting->is_running());
 126      }
 127  
 128      /**
 129       * Check delete instance
 130       *
 131       * @covers ::bigbluebuttonbn_delete_instance
 132       */
 133      public function test_bigbluebuttonbn_delete_instance_with_running_group_meetings() {
 134          $this->resetAfterTest();
 135          $this->initialise_mock_server();
 136          $datagenerator = $this->getDataGenerator();
 137          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 138          $course = $this->get_course();
 139          set_coursemodule_groupmode($bbactivitycm->id, VISIBLEGROUPS);
 140  
 141          $groups = [];
 142          foreach (['G1', 'G2'] as $gname) {
 143              $groups[] = $datagenerator->create_group(['courseid' => $course->id, 'name' => $gname]);
 144          }
 145          // Just create a user in one of the group so we check we don't just end meetings for this user...
 146          $user = $datagenerator->create_and_enrol($this->get_course());
 147          $groupids = array_map(function($g) {
 148              return $g->id;
 149          }, $groups);
 150          $datagenerator->create_group_member(['userid' => $user->id, 'groupid' => $groupids[0]]);
 151          $this->setUser($user);
 152  
 153          $groupids[] = 0; // Add no group (id=0) - as an item so it is covered in the loop.
 154          $bbbgenerator = $datagenerator->get_plugin_generator('mod_bigbluebuttonbn');
 155          $globalinstance = instance::get_from_instanceid($bbactivity->id);
 156          $meetings = [];
 157          foreach ($groupids as $groupid) {
 158              $instance = instance::get_group_instance_from_instance($globalinstance, $groupid);
 159              // Run the meetings.
 160              $bbbgenerator->create_meeting([
 161                  'instanceid' => $instance->get_instance_id(),
 162                  'groupid' => $instance->get_group_id(),
 163              ]);
 164              $meeting = new meeting($instance);
 165              $meeting->update_cache();
 166              $this->assertTrue($meeting->is_running());
 167              $meetings[] = $meeting;
 168          }
 169          $result = bigbluebuttonbn_delete_instance($bbactivity->id);
 170          $this->assertTrue($result);
 171          foreach ($meetings as $meeting) {
 172              $meeting->update_cache();
 173              $this->assertFalse($meeting->is_running());
 174          }
 175      }
 176      /**
 177       * Check user outline page
 178       *
 179       * @covers ::bigbluebuttonbn_user_outline
 180       */
 181      public function test_bigbluebuttonbn_user_outline() {
 182          $this->resetAfterTest();
 183  
 184          $generator = $this->getDataGenerator();
 185          $user = $generator->create_user();
 186          $this->setUser($user);
 187  
 188          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance($this->get_course(),
 189              ['completion' => 2, 'completionview' => 1]);
 190          $result = bigbluebuttonbn_user_outline($this->get_course(), $user, $bbactivitycm, $bbactivity);
 191          $this->assertEquals((object) ['info' => '', 'time' => 0], $result);
 192  
 193          bigbluebuttonbn_view($bbactivity, $this->get_course(), $bbactivitycm, $bbactivitycontext);
 194          $result = bigbluebuttonbn_user_outline($this->get_course(), $user, $bbactivitycm, $bbactivity);
 195          $this->assertStringContainsString(get_string('report_room_view', 'mod_bigbluebuttonbn'), $result->info);
 196      }
 197  
 198      /**
 199       * Check user completion
 200       *
 201       * @covers ::bigbluebuttonbn_user_complete
 202       */
 203      public function test_bigbluebuttonbn_user_complete() {
 204          $this->initialise_mock_server();
 205          $this->resetAfterTest();
 206  
 207          $generator = $this->getDataGenerator();
 208          $user = $generator->create_and_enrol($this->get_course());
 209          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance($this->get_course(),
 210              ['completion' => 2, 'completionview' => 1]);
 211          $this->setUser($user);
 212  
 213          // Now create a couple of logs.
 214          bigbluebuttonbn_view($bbactivity, $this->get_course(), $bbactivitycm, $bbactivitycontext);
 215          ob_start();
 216          bigbluebuttonbn_user_complete($this->get_course(), $user, $bbactivitycm, $bbactivity);
 217          $output = ob_get_contents();
 218          ob_end_clean();
 219          $this->assertStringContainsString(get_string('report_room_view', 'mod_bigbluebuttonbn'), $output);
 220      }
 221  
 222      /**
 223       * Check get recent activity
 224       *
 225       * @covers ::bigbluebuttonbn_get_recent_mod_activity
 226       */
 227      public function test_bigbluebuttonbn_get_recent_mod_activity() {
 228          $this->initialise_mock_server();
 229          $this->resetAfterTest();
 230  
 231          $generator = $this->getDataGenerator();
 232          $user = $generator->create_and_enrol($this->get_course());
 233          $this->setUser($user);
 234          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 235          // Now create a couple of logs.
 236          $instance = instance::get_from_instanceid($bbactivity->id);
 237          $recordings = $this->create_recordings_for_instance($instance, [['name' => "Pre-Recording 1"]]);
 238          logger::log_meeting_joined_event($instance, 0);
 239          logger::log_meeting_joined_event($instance, 0);
 240          logger::log_recording_played_event($instance, $recordings[0]->id);
 241  
 242          $activities = $this->prepare_for_recent_activity_array(0, $user->id, 0);
 243          $this->assertCount(4, $activities);
 244          $this->assertEquals(
 245              ["Meeting joined", "Meeting joined", "Recording viewed"],
 246              array_values(
 247                  array_filter(
 248                      array_map(function($activity) {
 249                          return $activity->eventname ?? "";
 250                      }, $activities),
 251                      function($e) {
 252                          return !empty($e);
 253                      }
 254                  )
 255              )
 256          );
 257          $this->assertEquals("Pre-Recording 1", $activities[3]->content); // The recording view event should contain the name
 258          // of the activity.
 259      }
 260  
 261      /**
 262       * Prepare the list of activities as is done in course recent activity
 263       *
 264       * @param int $date
 265       * @param int $user
 266       * @param int $group
 267       * @return array|void
 268       */
 269      protected function prepare_for_recent_activity_array($date, $user, $group) {
 270          // Same algorithm as in cource/recent.php, but stops at the first bbb activity.
 271          $course = $this->get_course();
 272          $modinfo = get_fast_modinfo($course->id);
 273          $sections = array();
 274          $index = 0;
 275          foreach ($modinfo->get_section_info_all() as $i => $section) {
 276              if (!empty($section->uservisible)) {
 277                  $sections[$i] = $section;
 278              }
 279          }
 280          foreach ($sections as $sectionnum => $section) {
 281  
 282              $activity = new stdClass();
 283              $activity->type = 'section';
 284              if ($section->section > 0) {
 285                  $activity->name = get_section_name($this->get_course(), $section);
 286              } else {
 287                  $activity->name = '';
 288              }
 289  
 290              $activity->visible = $section->visible;
 291              $activities[$index++] = $activity;
 292  
 293              if (empty($modinfo->sections[$sectionnum])) {
 294                  continue;
 295              }
 296  
 297              foreach ($modinfo->sections[$sectionnum] as $cmid) {
 298                  $cm = $modinfo->cms[$cmid];
 299  
 300                  if (!$cm->uservisible) {
 301                      continue;
 302                  }
 303  
 304                  if (!empty($filter) && $cm->modname != $filter) {
 305                      continue;
 306                  }
 307  
 308                  if (!empty($filtermodid) && $cmid != $filtermodid) {
 309                      continue;
 310                  }
 311  
 312                  if ($cm->modname == 'bigbluebuttonbn') {
 313                      return bigbluebuttonbn_get_recent_mod_activity($activities,
 314                          $index,
 315                          $date,
 316                          $course->id, $cmid,
 317                          $user,
 318                          $group);
 319                  }
 320              }
 321          }
 322  
 323      }
 324  
 325      /**
 326       * Check user recent activity
 327       *
 328       * @covers ::bigbluebuttonbn_print_recent_mod_activity
 329       */
 330      public function test_bigbluebuttonbn_print_recent_mod_activity() {
 331          $this->initialise_mock_server();
 332          $this->resetAfterTest();
 333  
 334          $generator = $this->getDataGenerator();
 335          $user = $generator->create_and_enrol($this->get_course());
 336          $this->setUser($user);
 337          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 338          // Now create a couple of logs.
 339          $instance = instance::get_from_instanceid($bbactivity->id);
 340          $recordings = $this->create_recordings_for_instance($instance, [['name' => "Pre-Recording 1"]]);
 341          logger::log_meeting_joined_event($instance, 0);
 342          logger::log_meeting_joined_event($instance, 0);
 343          logger::log_recording_played_event($instance, $recordings[0]->id);
 344  
 345          $activities = $this->prepare_for_recent_activity_array(0, $user->id, 0);
 346          ob_start();
 347          bigbluebuttonbn_print_recent_mod_activity($activities[1], $this->get_course()->id, false, [], false);
 348          $output = ob_get_contents();
 349          ob_end_clean();
 350          $this->assertStringContainsString('Meeting joined', $output);
 351      }
 352  
 353  
 354      /**
 355       * Check recent activity for the course
 356       *
 357       * @covers ::bigbluebuttonbn_print_recent_activity
 358       */
 359      public function test_bigbluebuttonbn_print_recent_activity() {
 360          global $CFG;
 361          $this->initialise_mock_server();
 362          $this->resetAfterTest();
 363  
 364          $generator = $this->getDataGenerator();
 365          $user = $generator->create_and_enrol($this->get_course());
 366          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 367          // Now create a couple of logs.
 368          $timestart = time() - HOURSECS;
 369          $instance = instance::get_from_instanceid($bbactivity->id);
 370          $recordings = $this->create_recordings_for_instance($instance, [['name' => "Pre-Recording 1"]]);
 371  
 372          $this->setUser($user); // Important so the logs are set to this user.
 373          logger::log_meeting_joined_event($instance, 0);
 374          logger::log_meeting_joined_event($instance, 0);
 375          logger::log_recording_played_event($instance, $recordings[0]->id);
 376  
 377          $this->setAdminUser();
 378          // Test that everything is displayed.
 379          ob_start();
 380          bigbluebuttonbn_print_recent_activity($this->get_course(), true, $timestart);
 381          $output = ob_get_contents();
 382          ob_end_clean();
 383          $this->assertStringContainsString('Meeting joined', $output);
 384          $this->assertStringContainsString(fullname($user), $output);
 385          // Test that username are displayed in a different format.
 386          $CFG->alternativefullnameformat = 'firstname lastname firstnamephonetic lastnamephonetic middlename alternatename';
 387          $expectedname = "$user->firstname $user->lastname $user->firstnamephonetic "
 388              . "$user->lastnamephonetic $user->middlename $user->alternatename";
 389          ob_start();
 390          bigbluebuttonbn_print_recent_activity($this->get_course(), false, $timestart);
 391          $output = ob_get_contents();
 392          ob_end_clean();
 393          $this->assertStringContainsString('Meeting joined', $output);
 394          $this->assertStringNotContainsString($expectedname, $output);
 395          // Test that nothing is displayed as per timestart.
 396          ob_start();
 397          bigbluebuttonbn_print_recent_activity($this->get_course(), true, time());
 398          $output = ob_get_contents();
 399          ob_end_clean();
 400          $this->assertEmpty($output);
 401      }
 402  
 403      /**
 404       * Check extra capabilities return value
 405       *
 406       * @covers ::bigbluebuttonbn_get_extra_capabilities
 407       */
 408      public function test_bigbluebuttonbn_get_extra_capabilities() {
 409          $this->resetAfterTest();
 410          $this->assertEquals(['moodle/site:accessallgroups'], bigbluebuttonbn_get_extra_capabilities());
 411      }
 412  
 413      /**
 414       * Check form definition
 415       *
 416       * @covers ::bigbluebuttonbn_reset_course_form_definition
 417       */
 418      public function test_bigbluebuttonbn_reset_course_form_definition() {
 419          global $CFG, $PAGE;
 420          $this->initialise_mock_server();
 421  
 422          $PAGE->set_course($this->get_course());
 423          $this->setAdminUser();
 424          $this->resetAfterTest();
 425          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 426          include_once($CFG->dirroot . '/mod/bigbluebuttonbn/mod_form.php');
 427          $data = new stdClass();
 428          $data->instance = $bbactivity;
 429          $data->id = $bbactivity->id;
 430          $data->course = $bbactivity->course;
 431  
 432          $form = new mod_bigbluebuttonbn_mod_form($data, 1, $bbactivitycm, $this->get_course());
 433          $refclass = new ReflectionClass("mod_bigbluebuttonbn_mod_form");
 434          $formprop = $refclass->getProperty('_form');
 435          $formprop->setAccessible(true);
 436  
 437          /* @var $mform MoodleQuickForm quickform object definition */
 438          $mform = $formprop->getValue($form);
 439          bigbluebuttonbn_reset_course_form_definition($mform);
 440          $this->assertNotNull($mform->getElement('bigbluebuttonbnheader'));
 441      }
 442  
 443      /**
 444       * Check defaults for form
 445       *
 446       * @covers ::bigbluebuttonbn_reset_course_form_defaults
 447       */
 448      public function test_bigbluebuttonbn_reset_course_form_defaults() {
 449          global $CFG;
 450          $this->resetAfterTest();
 451          $results = bigbluebuttonbn_reset_course_form_defaults($this->get_course());
 452          $this->assertEquals([
 453              'reset_bigbluebuttonbn_events' => 0,
 454              'reset_bigbluebuttonbn_tags' => 0,
 455              'reset_bigbluebuttonbn_logs' => 0,
 456              'reset_bigbluebuttonbn_recordings' => 0,
 457          ], $results);
 458      }
 459  
 460      /**
 461       * Reset user data
 462       *
 463       * @covers ::bigbluebuttonbn_reset_userdata
 464       */
 465      public function test_bigbluebuttonbn_reset_userdata() {
 466          global $DB;
 467          $this->resetAfterTest();
 468          $data = new stdClass();
 469          $user = $this->getDataGenerator()->create_user();
 470  
 471          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 472          $this->getDataGenerator()->enrol_user($user->id, $this->course->id);
 473          $this->setUser($user);
 474  
 475          logger::log_meeting_joined_event(instance::get_from_instanceid($bbactivity->id), 0);
 476          $data->courseid = $this->get_course()->id;
 477          $data->reset_bigbluebuttonbn_tags = true;
 478          $data->reset_bigbluebuttonbn_logs = true;
 479          $data->course = $bbactivity->course;
 480          // Add and Join.
 481          $this->assertCount(2, $DB->get_records('bigbluebuttonbn_logs', ['bigbluebuttonbnid' => $bbactivity->id]));
 482          $results = bigbluebuttonbn_reset_userdata($data);
 483          $this->assertCount(0, $DB->get_records('bigbluebuttonbn_logs', ['bigbluebuttonbnid' => $bbactivity->id]));
 484          $this->assertEquals([
 485              'component' => 'BigBlueButton',
 486              'item' => 'Deleted tags',
 487              'error' => false
 488          ],
 489              $results[0]
 490          );
 491      }
 492  
 493      /**
 494       * Reset user data in a course and checks it does not delete logs elsewhere
 495       *
 496       * @covers ::bigbluebuttonbn_reset_userdata
 497       */
 498      public function test_bigbluebuttonbn_reset_userdata_in_a_course() {
 499          global $DB;
 500          $this->resetAfterTest();
 501          $data = new stdClass();
 502          $user = $this->getDataGenerator()->create_user();
 503  
 504          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 505          $this->getDataGenerator()->enrol_user($user->id, $this->course->id);
 506          logger::log_meeting_joined_event(instance::get_from_instanceid($bbactivity->id), 0);
 507  
 508          // Now create another activity in a course and add a couple of logs.
 509          // Aim is to make sure that only logs from one course are deleted.
 510          $course1 = $this->getDataGenerator()->create_course();
 511          list($bbactivitycontext1, $bbactivitycm1, $bbactivity1) = $this->create_instance($course1);
 512          logger::log_meeting_joined_event(instance::get_from_instanceid($bbactivity1->id), 0);
 513  
 514          $data->courseid = $this->get_course()->id;
 515          $data->reset_bigbluebuttonbn_tags = true;
 516          $data->reset_bigbluebuttonbn_logs = true;
 517          $data->course = $bbactivity->course;
 518          // Add and Join.
 519          $this->assertCount(2, $DB->get_records('bigbluebuttonbn_logs', ['bigbluebuttonbnid' => $bbactivity->id]));
 520          $this->assertCount(2, $DB->get_records('bigbluebuttonbn_logs', ['bigbluebuttonbnid' => $bbactivity1->id]));
 521          bigbluebuttonbn_reset_userdata($data);
 522          $this->assertCount(0, $DB->get_records('bigbluebuttonbn_logs', ['bigbluebuttonbnid' => $bbactivity->id]));
 523          $this->assertCount(2, $DB->get_records('bigbluebuttonbn_logs', ['bigbluebuttonbnid' => $bbactivity1->id]));
 524      }
 525  
 526      /**
 527       * Reset user data in a course but do not delete logs
 528       *
 529       * @covers ::bigbluebuttonbn_reset_userdata
 530       */
 531      public function test_bigbluebuttonbn_reset_userdata_logs_not_deleted() {
 532          global $DB;
 533          $this->resetAfterTest();
 534          $data = new stdClass();
 535          $user = $this->getDataGenerator()->create_user();
 536  
 537          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 538          $this->getDataGenerator()->enrol_user($user->id, $this->course->id);
 539          $this->setUser($user);
 540          logger::log_meeting_joined_event(instance::get_from_instanceid($bbactivity->id), 0);
 541  
 542          $data->courseid = $this->get_course()->id;
 543          $data->reset_bigbluebuttonbn_logs = false;
 544          $data->course = $bbactivity->course;
 545          // Add and Join.
 546          $this->assertCount(2, $DB->get_records('bigbluebuttonbn_logs', ['bigbluebuttonbnid' => $bbactivity->id]));
 547          bigbluebuttonbn_reset_userdata($data);
 548          $this->assertCount(2, $DB->get_records('bigbluebuttonbn_logs', ['bigbluebuttonbnid' => $bbactivity->id]));
 549      }
 550  
 551      /**
 552       * Check course module
 553       *
 554       * @covers ::bigbluebuttonbn_get_coursemodule_info
 555       */
 556      public function test_bigbluebuttonbn_get_coursemodule_info() {
 557          $this->resetAfterTest();
 558          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 559          $info = bigbluebuttonbn_get_coursemodule_info($bbactivitycm);
 560          $this->assertEquals($info->name, $bbactivity->name);
 561      }
 562  
 563      /**
 564       * Check update since
 565       *
 566       * @covers ::bigbluebuttonbn_check_updates_since
 567       */
 568      public function test_bigbluebuttonbn_check_updates_since() {
 569          $this->resetAfterTest();
 570          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 571          $result = bigbluebuttonbn_check_updates_since($bbactivitycm, 0);
 572          $this->assertEquals(
 573              '{"configuration":{"updated":false},"contentfiles":{"updated":false},"introfiles":' .
 574              '{"updated":false},"completion":{"updated":false}}',
 575              json_encode($result)
 576          );
 577      }
 578  
 579      /**
 580       * Check event action (calendar)
 581       *
 582       * @covers ::mod_bigbluebuttonbn_core_calendar_provide_event_action
 583       */
 584      public function test_mod_bigbluebuttonbn_core_calendar_provide_event_action() {
 585          global $DB;
 586          $this->initialise_mock_server();
 587          $this->resetAfterTest();
 588          $this->setAdminUser();
 589          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 590  
 591          // Standard use case, the meeting start and we want add an action event to join the meeting.
 592          $event = $this->create_action_event($this->get_course(), $bbactivity, logger::EVENT_MEETING_START);
 593          $factory = new \core_calendar\action_factory();
 594          $actionevent = mod_bigbluebuttonbn_core_calendar_provide_event_action($event, $factory);
 595          $this->assertEquals("Join session", $actionevent->get_name());
 596  
 597          // User has already joined the meeting (there is log event EVENT_JOIN already for this user).
 598          $instance = instance::get_from_instanceid($bbactivity->id);
 599          logger::log_meeting_joined_event($instance, 0);
 600  
 601          $bbactivity->closingtime = time() - 1000;
 602          $bbactivity->openingtime = time() - 2000;
 603          $DB->update_record('bigbluebuttonbn', $bbactivity);
 604          $event = $this->create_action_event($this->get_course(), $bbactivity, logger::EVENT_MEETING_START);
 605          $actionevent = mod_bigbluebuttonbn_core_calendar_provide_event_action($event, $factory);
 606          $this->assertNull($actionevent);
 607      }
 608  
 609      /**
 610       * Creates an action event.
 611       *
 612       * @param stdClass $course The course the bigbluebutton activity is in
 613       * @param stdClass $bbbactivity The bigbluebutton activity to create an event for
 614       * @param string $eventtype The event type. eg. ASSIGN_EVENT_TYPE_DUE.
 615       * @return bool|calendar_event
 616       */
 617      private function create_action_event(stdClass $course, stdClass $bbbactivity, string $eventtype) {
 618          $event = new stdClass();
 619          $event->name = 'Calendar event';
 620          $event->modulename = 'bigbluebuttonbn';
 621          $event->courseid = $course->id;
 622          $event->instance = $bbbactivity->id;
 623          $event->type = CALENDAR_EVENT_TYPE_ACTION;
 624          $event->priority = CALENDAR_EVENT_USER_OVERRIDE_PRIORITY;
 625          $event->eventtype = $eventtype;
 626          $event->timestart = time();
 627  
 628          return calendar_event::create($event);
 629      }
 630  
 631      /**
 632       * Test setting navigation admin menu
 633       *
 634       * @covers ::bigbluebuttonbn_extend_settings_navigation
 635       */
 636      public function test_bigbluebuttonbn_extend_settings_navigation_admin() {
 637          global $PAGE, $CFG;
 638          $this->resetAfterTest();
 639          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 640          $CFG->bigbluebuttonbn_meetingevents_enabled = true;
 641  
 642          $PAGE->set_cm($bbactivitycm);
 643          $PAGE->set_context(context_module::instance($bbactivitycm->id));
 644          $PAGE->set_url('/mod/bigbluebuttonbn/view.php', ['id' => $bbactivitycm->id]);
 645          $settingnav = $PAGE->settingsnav;
 646  
 647          $this->setAdminUser();
 648          $node = navigation_node::create('testnavigationnode');
 649          bigbluebuttonbn_extend_settings_navigation($settingnav, $node);
 650          $this->assertCount(1, $node->get_children_key_list());
 651      }
 652  
 653      /**
 654       * Check additional setting menu
 655       *
 656       * @covers ::bigbluebuttonbn_extend_settings_navigation
 657       */
 658      public function test_bigbluebuttonbn_extend_settings_navigation_user() {
 659          global $PAGE, $CFG;
 660          $this->resetAfterTest();
 661  
 662          $generator = $this->getDataGenerator();
 663          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 664          $user = $generator->create_user();
 665          $this->setUser($user);
 666          list($course, $bbactivitycmuser) = get_course_and_cm_from_instance($bbactivity->id, 'bigbluebuttonbn');
 667  
 668          $CFG->bigbluebuttonbn_meetingevents_enabled = true;
 669  
 670          $PAGE->set_cm($bbactivitycmuser);
 671          $PAGE->set_context(context_module::instance($bbactivitycm->id));
 672          $PAGE->set_url('/mod/bigbluebuttonbn/view.php', ['id' => $bbactivitycm->id]);
 673  
 674          $settingnav = $PAGE->settingsnav;
 675          $node = navigation_node::create('testnavigationnode');
 676          bigbluebuttonbn_extend_settings_navigation($settingnav, $node);
 677          $this->assertCount(0, $node->get_children_key_list());
 678      }
 679  
 680      /**
 681       * Check the visibility on calendar
 682       * @covers ::mod_bigbluebuttonbn_core_calendar_is_event_visible
 683       */
 684      public function test_mod_bigbluebuttonbn_core_calendar_is_event_visible() {
 685          global $DB;
 686          $this->resetAfterTest();
 687          $this->setAdminUser();
 688          list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
 689          $bbactivity->closingtime = time() - 1000;
 690          $bbactivity->openingtime = time() - 2000;
 691          $DB->update_record('bigbluebuttonbn', $bbactivity);
 692          $event = $this->create_action_event($this->get_course(), $bbactivity, logger::EVENT_MEETING_START);
 693          $this->assertFalse(mod_bigbluebuttonbn_core_calendar_is_event_visible($event));
 694          $bbactivity->closingtime = time() + 1000;
 695          $DB->update_record('bigbluebuttonbn', $bbactivity);
 696          $event = $this->create_action_event($this->get_course(), $bbactivity, logger::EVENT_MEETING_START);
 697          $this->assertTrue(mod_bigbluebuttonbn_core_calendar_is_event_visible($event));
 698          $event->instance = 0;
 699          $this->assertFalse(mod_bigbluebuttonbn_core_calendar_is_event_visible($event));
 700      }
 701  
 702      /**
 703       * Check the bigbluebuttonbn_pre_enable_plugin_actions function.
 704       *
 705       * @covers ::bigbluebuttonbn_pre_enable_plugin_actions
 706       * @dataProvider bigbluebuttonbn_pre_enable_plugin_actions_provider
 707       * @param bool $initialstate
 708       * @param bool $expected
 709       * @param int $notificationcount
 710       */
 711      public function test_bigbluebuttonbn_pre_enable_plugin_actions(
 712          ?bool $initialstate,
 713          bool $expected,
 714          int $notificationcount
 715      ): void {
 716          $this->resetAfterTest(true);
 717  
 718          set_config('bigbluebuttonbn_default_dpa_accepted', $initialstate);
 719  
 720          $this->assertEquals($expected, bigbluebuttonbn_pre_enable_plugin_actions());
 721          $this->assertCount($notificationcount, \core\notification::fetch());
 722      }
 723  
 724      /**
 725       * Check the bigbluebuttonbn_pre_enable_plugin_actions function.
 726       *
 727       * @covers ::bigbluebuttonbn_pre_enable_plugin_actions
 728       * @dataProvider bigbluebuttonbn_pre_enable_plugin_actions_provider
 729       * @param bool $initialstate
 730       * @param bool $expected
 731       * @param int $notificationcount
 732       */
 733      public function test_enable_plugin(
 734          ?bool $initialstate,
 735          bool $expected,
 736          int $notificationcount
 737      ): void {
 738          $this->resetAfterTest(true);
 739  
 740          set_config('bigbluebuttonbn_default_dpa_accepted', $initialstate);
 741          $this->assertEquals($expected, \core\plugininfo\mod::enable_plugin('bigbluebuttonbn', 1));
 742          $this->assertCount($notificationcount, \core\notification::fetch());
 743      }
 744  
 745      /**
 746       * Data provider for bigbluebuttonbn_pre_enable_plugin_actions tests.
 747       *
 748       * @return array
 749       */
 750      public function bigbluebuttonbn_pre_enable_plugin_actions_provider(): array {
 751          return [
 752              'Initially unset' => [
 753                  null,
 754                  false,
 755                  1,
 756              ],
 757              'Set to false' => [
 758                  false,
 759                  false,
 760                  1,
 761              ],
 762              'Initially set' => [
 763                  true,
 764                  true,
 765                  0,
 766              ],
 767          ];
 768      }
 769  }