PageRenderTime 29ms CodeModel.GetById 7ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 1ms

/mod/scorm/tests/events_test.php

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