Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310]

   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   * This file contains tests for scorm events.
  19   *
  20   * @package    mod_scorm
  21   * @copyright  2013 onwards Ankit Agarwal
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  global $CFG;
  26  require_once($CFG->dirroot . '/mod/scorm/locallib.php');
  27  require_once($CFG->dirroot . '/mod/scorm/lib.php');
  28  
  29  /**
  30   * Test class for various events related to Scorm.
  31   *
  32   * @package    mod_scorm
  33   * @copyright  2013 onwards Ankit Agarwal
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class mod_scorm_event_testcase extends advanced_testcase {
  37  
  38      /** @var stdClass store course object */
  39      protected $eventcourse;
  40  
  41      /** @var stdClass store user object */
  42      protected $eventuser;
  43  
  44      /** @var stdClass store scorm object */
  45      protected $eventscorm;
  46  
  47      /** @var stdClass store course module object */
  48      protected $eventcm;
  49  
  50      protected function setUp(): void {
  51          $this->setAdminUser();
  52          $this->eventcourse = $this->getDataGenerator()->create_course();
  53          $this->eventuser = $this->getDataGenerator()->create_user();
  54          $record = new stdClass();
  55          $record->course = $this->eventcourse->id;
  56          $this->eventscorm = $this->getDataGenerator()->create_module('scorm', $record);
  57          $this->eventcm = get_coursemodule_from_instance('scorm', $this->eventscorm->id);
  58      }
  59  
  60      /**
  61       * Tests for attempt deleted event
  62       */
  63      public function test_attempt_deleted_event() {
  64  
  65          global $USER;
  66  
  67          $this->resetAfterTest();
  68          scorm_insert_track(2, $this->eventscorm->id, 1, 4, 'cmi.core.score.raw', 10);
  69          $sink = $this->redirectEvents();
  70          scorm_delete_attempt(2, $this->eventscorm, 4);
  71          $events = $sink->get_events();
  72          $sink->close();
  73          $event = reset($events);
  74  
  75          // Verify data.
  76          $this->assertCount(3, $events);
  77          $this->assertInstanceOf('\mod_scorm\event\attempt_deleted', $event);
  78          $this->assertEquals($USER->id, $event->userid);
  79          $this->assertEquals(context_module::instance($this->eventcm->id), $event->get_context());
  80          $this->assertEquals(4, $event->other['attemptid']);
  81          $this->assertEquals(2, $event->relateduserid);
  82          $expected = array($this->eventcourse->id, 'scorm', 'delete attempts', 'report.php?id=' . $this->eventcm->id,
  83                  4, $this->eventcm->id);
  84          $this->assertEventLegacyLogData($expected, $events[0]);
  85          $this->assertEventContextNotUsed($event);
  86  
  87          // Test event validations.
  88          $this->expectException(coding_exception::class);
  89          \mod_scorm\event\attempt_deleted::create(array(
  90              'contextid' => 5,
  91              'relateduserid' => 2
  92          ));
  93      }
  94  
  95      /**
  96       * Tests for course module viewed event.
  97       *
  98       * There is no api involved so the best we can do is test legacy data by triggering event manually.
  99       */
 100      public function test_course_module_viewed_event() {
 101          $this->resetAfterTest();
 102          $event = \mod_scorm\event\course_module_viewed::create(array(
 103              'objectid' => $this->eventscorm->id,
 104              'context' => context_module::instance($this->eventcm->id),
 105              'courseid' => $this->eventcourse->id
 106          ));
 107  
 108          // Trigger and capture the event.
 109          $sink = $this->redirectEvents();
 110          $event->trigger();
 111          $events = $sink->get_events();
 112          $event = reset($events);
 113  
 114          // Check that the legacy log data is valid.
 115          $expected = array($this->eventcourse->id, 'scorm', 'pre-view', 'view.php?id=' . $this->eventcm->id,
 116                  $this->eventscorm->id, $this->eventcm->id);
 117          $this->assertEventLegacyLogData($expected, $event);
 118          $this->assertEventContextNotUsed($event);
 119      }
 120  
 121      /**
 122       * Tests for instance list viewed event.
 123       *
 124       * There is no api involved so the best we can do is test legacy data by triggering event manually.
 125       */
 126      public function test_course_module_instance_list_viewed_event() {
 127          $this->resetAfterTest();
 128          $event = \mod_scorm\event\course_module_instance_list_viewed::create(array(
 129              'context' => context_course::instance($this->eventcourse->id),
 130              'courseid' => $this->eventcourse->id
 131          ));
 132  
 133          // Trigger and capture the event.
 134          $sink = $this->redirectEvents();
 135          $event->trigger();
 136          $events = $sink->get_events();
 137          $event = reset($events);
 138  
 139          // Check that the legacy log data is valid.
 140          $expected = array($this->eventcourse->id, 'scorm', 'view all', 'index.php?id=' . $this->eventcourse->id, '');
 141          $this->assertEventLegacyLogData($expected, $event);
 142          $this->assertEventContextNotUsed($event);
 143      }
 144  
 145      /**
 146       * Tests for interactions viewed.
 147       *
 148       * There is no api involved so the best we can do is test legacy data by triggering event manually and test validations.
 149       */
 150      public function test_interactions_viewed_event() {
 151          $this->resetAfterTest();
 152          $event = \mod_scorm\event\interactions_viewed::create(array(
 153              'relateduserid' => 5,
 154              'context' => context_module::instance($this->eventcm->id),
 155              'courseid' => $this->eventcourse->id,
 156              'other' => array('attemptid' => 2, 'instanceid' => $this->eventscorm->id)
 157          ));
 158  
 159          // Trigger and capture the event.
 160          $sink = $this->redirectEvents();
 161          $event->trigger();
 162          $events = $sink->get_events();
 163          $event = reset($events);
 164  
 165          // Check that the legacy log data is valid.
 166          $expected = array($this->eventcourse->id, 'scorm', 'userreportinteractions', 'report/userreportinteractions.php?id=' .
 167                  $this->eventcm->id . '&user=5&attempt=' . 2, $this->eventscorm->id, $this->eventcm->id);
 168          $this->assertEventLegacyLogData($expected, $event);
 169          $this->assertEventContextNotUsed($event);
 170      }
 171  
 172      /**
 173       * Tests for interactions viewed validations.
 174       */
 175      public function test_interactions_viewed_event_validations() {
 176          $this->resetAfterTest();
 177          try {
 178              \mod_scorm\event\interactions_viewed::create(array(
 179                  'context' => context_module::instance($this->eventcm->id),
 180                  'courseid' => $this->eventcourse->id,
 181                  'other' => array('attemptid' => 2)
 182              ));
 183              $this->fail("Event validation should not allow \\mod_scorm\\event\\interactions_viewed to be triggered without
 184                      other['instanceid']");
 185          } catch (Exception $e) {
 186              $this->assertInstanceOf('coding_exception', $e);
 187          }
 188          try {
 189              \mod_scorm\event\interactions_viewed::create(array(
 190                  'context' => context_module::instance($this->eventcm->id),
 191                  'courseid' => $this->eventcourse->id,
 192                  'other' => array('instanceid' => 2)
 193              ));
 194              $this->fail("Event validation should not allow \\mod_scorm\\event\\interactions_viewed to be triggered without
 195                      other['attemptid']");
 196          } catch (Exception $e) {
 197              $this->assertInstanceOf('coding_exception', $e);
 198          }
 199      }
 200  
 201      /** Tests for report viewed.
 202       *
 203       * There is no api involved so the best we can do is test legacy data and validations by triggering event manually.
 204       */
 205      public function test_report_viewed_event() {
 206          $this->resetAfterTest();
 207          $event = \mod_scorm\event\report_viewed::create(array(
 208               'context' => context_module::instance($this->eventcm->id),
 209               'courseid' => $this->eventcourse->id,
 210               'other' => array(
 211                   'scormid' => $this->eventscorm->id,
 212                   'mode' => 'basic'
 213               )
 214          ));
 215  
 216          // Trigger and capture the event.
 217          $sink = $this->redirectEvents();
 218          $event->trigger();
 219          $events = $sink->get_events();
 220          $event = reset($events);
 221  
 222          // Check that the legacy log data is valid.
 223          $expected = array($this->eventcourse->id, 'scorm', 'report', 'report.php?id=' . $this->eventcm->id . '&mode=basic',
 224                  $this->eventscorm->id, $this->eventcm->id);
 225          $this->assertEventLegacyLogData($expected, $event);
 226          $this->assertEventContextNotUsed($event);
 227      }
 228  
 229      /** Tests for sco launched event.
 230       *
 231       * There is no api involved so the best we can do is test legacy data and validations by triggering event manually.
 232       */
 233      public function test_sco_launched_event() {
 234          $this->resetAfterTest();
 235          $event = \mod_scorm\event\sco_launched::create(array(
 236               'objectid' => 2,
 237               'context' => context_module::instance($this->eventcm->id),
 238               'courseid' => $this->eventcourse->id,
 239               'other' => array('loadedcontent' => 'url_to_content_that_was_laoded.php')
 240          ));
 241  
 242          // Trigger and capture the event.
 243          $sink = $this->redirectEvents();
 244          $event->trigger();
 245          $events = $sink->get_events();
 246          $event = reset($events);
 247  
 248          // Check that the legacy log data is valid.
 249          $expected = array($this->eventcourse->id, 'scorm', 'launch', 'view.php?id=' . $this->eventcm->id,
 250                            'url_to_content_that_was_laoded.php', $this->eventcm->id);
 251          $this->assertEventLegacyLogData($expected, $event);
 252          $this->assertEventContextNotUsed($event);
 253  
 254          // Test validations.
 255          $this->expectException(coding_exception::class);
 256          \mod_scorm\event\sco_launched::create(array(
 257               'objectid' => $this->eventscorm->id,
 258               'context' => context_module::instance($this->eventcm->id),
 259               'courseid' => $this->eventcourse->id,
 260          ));
 261      }
 262  
 263      /**
 264       * Tests for tracks viewed event.
 265       *
 266       * There is no api involved so the best we can do is test validations by triggering event manually.
 267       */
 268      public function test_tracks_viewed_event() {
 269          $this->resetAfterTest();
 270          $event = \mod_scorm\event\tracks_viewed::create(array(
 271              'relateduserid' => 5,
 272              'context' => context_module::instance($this->eventcm->id),
 273              'courseid' => $this->eventcourse->id,
 274              'other' => array('attemptid' => 2, 'instanceid' => $this->eventscorm->id, 'scoid' => 3)
 275          ));
 276  
 277          // Trigger and capture the event.
 278          $sink = $this->redirectEvents();
 279          $event->trigger();
 280          $events = $sink->get_events();
 281          $event = reset($events);
 282  
 283          // Check that the legacy log data is valid.
 284          $expected = array($this->eventcourse->id, 'scorm', 'userreporttracks', 'report/userreporttracks.php?id=' .
 285                  $this->eventcm->id . '&user=5&attempt=' . 2 . '&scoid=3', $this->eventscorm->id, $this->eventcm->id);
 286          $this->assertEventLegacyLogData($expected, $event);
 287          $this->assertEventContextNotUsed($event);
 288      }
 289  
 290      /**
 291       * Tests for tracks viewed event validations.
 292       */
 293      public function test_tracks_viewed_event_validations() {
 294          $this->resetAfterTest();
 295          try {
 296              \mod_scorm\event\tracks_viewed::create(array(
 297                  'context' => context_module::instance($this->eventcm->id),
 298                  'courseid' => $this->eventcourse->id,
 299                  'other' => array('attemptid' => 2, 'scoid' => 2)
 300              ));
 301              $this->fail("Event validation should not allow \\mod_scorm\\event\\tracks_viewed to be triggered without
 302                      other['instanceid']");
 303          } catch (Exception $e) {
 304              $this->assertInstanceOf('coding_exception', $e);
 305          }
 306          try {
 307              \mod_scorm\event\tracks_viewed::create(array(
 308                  'context' => context_module::instance($this->eventcm->id),
 309                  'courseid' => $this->eventcourse->id,
 310                  'other' => array('instanceid' => 2, 'scoid' => 2)
 311              ));
 312              $this->fail("Event validation should not allow \\mod_scorm\\event\\tracks_viewed to be triggered without
 313                      other['attemptid']");
 314          } catch (Exception $e) {
 315              $this->assertInstanceOf('coding_exception', $e);
 316          }
 317  
 318          try {
 319              \mod_scorm\event\tracks_viewed::create(array(
 320                  'context' => context_module::instance($this->eventcm->id),
 321                  'courseid' => $this->eventcourse->id,
 322                  'other' => array('attemptid' => 2, 'instanceid' => 2)
 323              ));
 324              $this->fail("Event validation should not allow \\mod_scorm\\event\\tracks_viewed to be triggered without
 325                      other['scoid']");
 326          } catch (Exception $e) {
 327              $this->assertInstanceOf('coding_exception', $e);
 328          }
 329      }
 330  
 331      /**
 332       * Tests for userreport viewed event.
 333       *
 334       * There is no api involved so the best we can do is test validations and legacy log by triggering event manually.
 335       */
 336      public function test_user_report_viewed_event() {
 337          $this->resetAfterTest();
 338          $event = \mod_scorm\event\user_report_viewed::create(array(
 339              'relateduserid' => 5,
 340              'context' => context_module::instance($this->eventcm->id),
 341              'courseid' => $this->eventcourse->id,
 342              'other' => array('attemptid' => 2, 'instanceid' => $this->eventscorm->id)
 343          ));
 344  
 345          // Trigger and capture the event.
 346          $sink = $this->redirectEvents();
 347          $event->trigger();
 348          $events = $sink->get_events();
 349          $event = reset($events);
 350  
 351          // Check that the legacy log data is valid.
 352          $expected = array($this->eventcourse->id, 'scorm', 'userreport', 'report/userreport.php?id=' .
 353                  $this->eventcm->id . '&user=5&attempt=' . 2, $this->eventscorm->id, $this->eventcm->id);
 354          $this->assertEventLegacyLogData($expected, $event);
 355          $this->assertEventContextNotUsed($event);
 356      }
 357  
 358      /**
 359       * Tests for userreport viewed event validations.
 360       */
 361      public function test_user_report_viewed_event_validations() {
 362          $this->resetAfterTest();
 363          try {
 364              \mod_scorm\event\user_report_viewed::create(array(
 365                  'context' => context_module::instance($this->eventcm->id),
 366                  'courseid' => $this->eventcourse->id,
 367                  'other' => array('attemptid' => 2)
 368              ));
 369              $this->fail("Event validation should not allow \\mod_scorm\\event\\user_report_viewed to be triggered without
 370                      other['instanceid']");
 371          } catch (Exception $e) {
 372              $this->assertInstanceOf('coding_exception', $e);
 373          }
 374          try {
 375              \mod_scorm\event\user_report_viewed::create(array(
 376                  'context' => context_module::instance($this->eventcm->id),
 377                  'courseid' => $this->eventcourse->id,
 378                  'other' => array('instanceid' => 2)
 379              ));
 380              $this->fail("Event validation should not allow \\mod_scorm\\event\\user_report_viewed to be triggered without
 381                      other['attemptid']");
 382          } catch (Exception $e) {
 383              $this->assertInstanceOf('coding_exception', $e);
 384          }
 385      }
 386  
 387      /**
 388       * dataProvider for test_scoreraw_submitted_event().
 389       */
 390      public function get_scoreraw_submitted_event_provider() {
 391          return array(
 392              // SCORM 1.2.
 393              // - cmi.core.score.raw.
 394              'cmi.core.score.raw => 100' => array('cmi.core.score.raw', '100'),
 395              'cmi.core.score.raw => 90' => array('cmi.core.score.raw', '90'),
 396              'cmi.core.score.raw => 50' => array('cmi.core.score.raw', '50'),
 397              'cmi.core.score.raw => 10' => array('cmi.core.score.raw', '10'),
 398              // Check an edge case (PHP empty() vs isset()): score value equals to '0'.
 399              'cmi.core.score.raw => 0' => array('cmi.core.score.raw', '0'),
 400              // SCORM 1.3 AKA 2004.
 401              // - cmi.score.raw.
 402              'cmi.score.raw => 100' => array('cmi.score.raw', '100'),
 403              'cmi.score.raw => 90' => array('cmi.score.raw', '90'),
 404              'cmi.score.raw => 50' => array('cmi.score.raw', '50'),
 405              'cmi.score.raw => 10' => array('cmi.score.raw', '10'),
 406              // Check an edge case (PHP empty() vs isset()): score value equals to '0'.
 407              'cmi.score.raw => 0' => array('cmi.score.raw', '0'),
 408          );
 409      }
 410  
 411      /**
 412       * Tests for score submitted event.
 413       *
 414       * There is no api involved so the best we can do is test data by triggering event manually.
 415       *
 416       * @dataProvider get_scoreraw_submitted_event_provider
 417       *
 418       * @param string $cmielement a valid CMI raw score element
 419       * @param string $cmivalue a valid CMI raw score value
 420       */
 421      public function test_scoreraw_submitted_event($cmielement, $cmivalue) {
 422          $this->resetAfterTest();
 423          $event = \mod_scorm\event\scoreraw_submitted::create(array(
 424              'other' => array('attemptid' => '2', 'cmielement' => $cmielement, 'cmivalue' => $cmivalue),
 425              'objectid' => $this->eventscorm->id,
 426              'context' => context_module::instance($this->eventcm->id),
 427              'relateduserid' => $this->eventuser->id
 428          ));
 429  
 430          // Trigger and capture the event.
 431          $sink = $this->redirectEvents();
 432          $event->trigger();
 433          $events = $sink->get_events();
 434          $sink->close();
 435          $event = reset($events);
 436          $this->assertEquals(2, $event->other['attemptid']);
 437          $this->assertEquals($cmielement, $event->other['cmielement']);
 438          $this->assertEquals($cmivalue, $event->other['cmivalue']);
 439  
 440          // Check that no legacy log data is provided.
 441          $this->assertEventLegacyLogData(null, $event);
 442          $this->assertEventContextNotUsed($event);
 443      }
 444  
 445      /**
 446       * dataProvider for test_scoreraw_submitted_event_validations().
 447       */
 448      public function get_scoreraw_submitted_event_validations() {
 449          return array(
 450              'scoreraw_submitted => missing cmielement' => array(
 451                  null, '50',
 452                  "Event validation should not allow \\mod_scorm\\event\\scoreraw_submitted " .
 453                      "to be triggered without other['cmielement']",
 454                  'Coding error detected, it must be fixed by a programmer: ' .
 455                      "The 'cmielement' must be set in other."
 456              ),
 457              'scoreraw_submitted => missing cmivalue' => array(
 458                  'cmi.core.score.raw', null,
 459                  "Event validation should not allow \\mod_scorm\\event\\scoreraw_submitted " .
 460                      "to be triggered without other['cmivalue']",
 461                  'Coding error detected, it must be fixed by a programmer: ' .
 462                      "The 'cmivalue' must be set in other."
 463              ),
 464              'scoreraw_submitted => wrong CMI element' => array(
 465                  'cmi.core.lesson_status', '50',
 466                  "Event validation should not allow \\mod_scorm\\event\\scoreraw_submitted " .
 467                      'to be triggered with a CMI element not representing a raw score',
 468                  'Coding error detected, it must be fixed by a programmer: ' .
 469                      "The 'cmielement' must represents a valid CMI raw score (cmi.core.lesson_status)."
 470              ),
 471          );
 472      }
 473  
 474      /**
 475       * Tests for score submitted event validations.
 476       *
 477       * @dataProvider get_scoreraw_submitted_event_validations
 478       *
 479       * @param string $cmielement a valid CMI raw score element
 480       * @param string $cmivalue a valid CMI raw score value
 481       * @param string $failmessage the message used to fail the test in case of missing to violate a validation rule
 482       * @param string $excmessage the exception message when violating the validations rules
 483       */
 484      public function test_scoreraw_submitted_event_validations($cmielement, $cmivalue, $failmessage, $excmessage) {
 485          $this->resetAfterTest();
 486          try {
 487              $data = array(
 488                  'context' => context_module::instance($this->eventcm->id),
 489                  'courseid' => $this->eventcourse->id,
 490                  'other' => array('attemptid' => 2)
 491              );
 492              if ($cmielement != null) {
 493                  $data['other']['cmielement'] = $cmielement;
 494              }
 495              if ($cmivalue != null) {
 496                  $data['other']['cmivalue'] = $cmivalue;
 497              }
 498              \mod_scorm\event\scoreraw_submitted::create($data);
 499              $this->fail($failmessage);
 500          } catch (Exception $e) {
 501              $this->assertInstanceOf('coding_exception', $e);
 502              $this->assertEquals($excmessage, $e->getMessage());
 503          }
 504      }
 505  
 506      /**
 507       * dataProvider for test_status_submitted_event().
 508       */
 509      public function get_status_submitted_event_provider() {
 510          return array(
 511              // SCORM 1.2.
 512              // 1. Status: cmi.core.lesson_status.
 513              'cmi.core.lesson_status => passed' => array('cmi.core.lesson_status', 'passed'),
 514              'cmi.core.lesson_status => completed' => array('cmi.core.lesson_status', 'completed'),
 515              'cmi.core.lesson_status => failed' => array('cmi.core.lesson_status', 'failed'),
 516              'cmi.core.lesson_status => incomplete' => array('cmi.core.lesson_status', 'incomplete'),
 517              'cmi.core.lesson_status => browsed' => array('cmi.core.lesson_status', 'browsed'),
 518              'cmi.core.lesson_status => not attempted' => array('cmi.core.lesson_status', 'not attempted'),
 519              // SCORM 1.3 AKA 2004.
 520              // 1. Completion status: cmi.completion_status.
 521              'cmi.completion_status => completed' => array('cmi.completion_status', 'completed'),
 522              'cmi.completion_status => incomplete' => array('cmi.completion_status', 'incomplete'),
 523              'cmi.completion_status => not attempted' => array('cmi.completion_status', 'not attempted'),
 524              'cmi.completion_status => unknown' => array('cmi.completion_status', 'unknown'),
 525              // 2. Success status: cmi.success_status.
 526              'cmi.success_status => passed' => array('cmi.success_status', 'passed'),
 527              'cmi.success_status => failed' => array('cmi.success_status', 'failed'),
 528              'cmi.success_status => unknown' => array('cmi.success_status', 'unknown')
 529          );
 530      }
 531  
 532      /**
 533       * Tests for status submitted event.
 534       *
 535       * There is no api involved so the best we can do is test data by triggering event manually.
 536       *
 537       * @dataProvider get_status_submitted_event_provider
 538       *
 539       * @param string $cmielement a valid CMI status element
 540       * @param string $cmivalue a valid CMI status value
 541       */
 542      public function test_status_submitted_event($cmielement, $cmivalue) {
 543          $this->resetAfterTest();
 544          $event = \mod_scorm\event\status_submitted::create(array(
 545              'other' => array('attemptid' => '2', 'cmielement' => $cmielement, 'cmivalue' => $cmivalue),
 546              'objectid' => $this->eventscorm->id,
 547              'context' => context_module::instance($this->eventcm->id),
 548              'relateduserid' => $this->eventuser->id
 549          ));
 550  
 551          // Trigger and capture the event.
 552          $sink = $this->redirectEvents();
 553          $event->trigger();
 554          $events = $sink->get_events();
 555          $sink->close();
 556          $event = reset($events);
 557          $this->assertEquals(2, $event->other['attemptid']);
 558          $this->assertEquals($cmielement, $event->other['cmielement']);
 559          $this->assertEquals($cmivalue, $event->other['cmivalue']);
 560  
 561          // Check that no legacy log data is provided.
 562          $this->assertEventLegacyLogData(null, $event);
 563          $this->assertEventContextNotUsed($event);
 564      }
 565  
 566      /**
 567       * dataProvider for test_status_submitted_event_validations().
 568       */
 569      public function get_status_submitted_event_validations() {
 570          return array(
 571              'status_submitted => missing cmielement' => array(
 572                  null, 'passed',
 573                  "Event validation should not allow \\mod_scorm\\event\\status_submitted " .
 574                      "to be triggered without other['cmielement']",
 575                  'Coding error detected, it must be fixed by a programmer: ' .
 576                      "The 'cmielement' must be set in other."
 577              ),
 578              'status_submitted => missing cmivalue' => array(
 579                  'cmi.core.lesson_status', null,
 580                  "Event validation should not allow \\mod_scorm\\event\\status_submitted " .
 581                      "to be triggered without other['cmivalue']",
 582                  'Coding error detected, it must be fixed by a programmer: ' .
 583                      "The 'cmivalue' must be set in other."
 584              ),
 585              'status_submitted => wrong CMI element' => array(
 586                  'cmi.core.score.raw', 'passed',
 587                  "Event validation should not allow \\mod_scorm\\event\\status_submitted " .
 588                      'to be triggered with a CMI element not representing a valid CMI status element',
 589                  'Coding error detected, it must be fixed by a programmer: ' .
 590                      "The 'cmielement' must represents a valid CMI status element (cmi.core.score.raw)."
 591              ),
 592              'status_submitted => wrong CMI value' => array(
 593                  'cmi.core.lesson_status', 'blahblahblah',
 594                  "Event validation should not allow \\mod_scorm\\event\\status_submitted " .
 595                      'to be triggered with a CMI element not representing a valid CMI status',
 596                  'Coding error detected, it must be fixed by a programmer: ' .
 597                      "The 'cmivalue' must represents a valid CMI status value (blahblahblah)."
 598              ),
 599          );
 600      }
 601  
 602      /**
 603       * Tests for status submitted event validations.
 604       *
 605       * @dataProvider get_status_submitted_event_validations
 606       *
 607       * @param string $cmielement a valid CMI status element
 608       * @param string $cmivalue a valid CMI status value
 609       * @param string $failmessage the message used to fail the test in case of missing to violate a validation rule
 610       * @param string $excmessage the exception message when violating the validations rules
 611       */
 612      public function test_status_submitted_event_validations($cmielement, $cmivalue, $failmessage, $excmessage) {
 613          $this->resetAfterTest();
 614          try {
 615              $data = array(
 616                  'context' => context_module::instance($this->eventcm->id),
 617                  'courseid' => $this->eventcourse->id,
 618                  'other' => array('attemptid' => 2)
 619              );
 620              if ($cmielement != null) {
 621                  $data['other']['cmielement'] = $cmielement;
 622              }
 623              if ($cmivalue != null) {
 624                  $data['other']['cmivalue'] = $cmivalue;
 625              }
 626              \mod_scorm\event\status_submitted::create($data);
 627              $this->fail($failmessage);
 628          } catch (Exception $e) {
 629              $this->assertInstanceOf('coding_exception', $e);
 630              $this->assertEquals($excmessage, $e->getMessage());
 631          }
 632      }
 633  }