first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+978
View File
@@ -0,0 +1,978 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/..//fixtures/event_fixtures.php');
/**
* Tests for event manager, base event and observers.
*
* @package core
* @category phpunit
* @copyright 2013 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class base_test extends \advanced_testcase {
const DEBUGGING_MSG = 'Events API using $handlers array has been deprecated in favour of Events 2 API, please use it instead.';
public function test_event_properties(): void {
global $USER;
$system = \context_system::instance();
$event = \core_tests\event\unittest_executed::create(array('context'=>$system, 'objectid'=>5, 'other'=>array('sample'=>null, 'xx'=>10)));
$this->assertSame('\core_tests\event\unittest_executed', $event->eventname);
$this->assertSame('core_tests', $event->component);
$this->assertSame('executed', $event->action);
$this->assertSame('unittest', $event->target);
$this->assertSame(5, $event->objectid);
$this->assertSame('u', $event->crud);
$this->assertSame(\core\event\base::LEVEL_PARTICIPATING, $event->edulevel);
$this->assertEquals($system, $event->get_context());
$this->assertSame($system->id, $event->contextid);
$this->assertSame($system->contextlevel, $event->contextlevel);
$this->assertSame($system->instanceid, $event->contextinstanceid);
$this->assertSame($USER->id, $event->userid);
$this->assertSame(0, $event->courseid);
$this->assertNull($event->relateduserid);
$this->assertFalse(isset($event->relateduserid));
$this->assertSame(0, $event->anonymous);
$this->assertSame(array('sample'=>null, 'xx'=>10), $event->other);
$this->assertTrue(isset($event->other['xx']));
$this->assertFalse(isset($event->other['sample']));
$this->assertLessThanOrEqual(time(), $event->timecreated);
try {
$event->courseid = 2;
$this->fail('Exception expected on event modification');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
try {
$event->xxxx = 1;
$this->fail('Exception expected on event modification');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
$event2 = \core_tests\event\unittest_executed::create(array('contextid'=>$system->id, 'objectid'=>5, 'anonymous'=>1, 'other'=>array('sample'=>null, 'xx'=>10)));
$this->assertEquals($event->get_context(), $event2->get_context());
$this->assertSame(1, $event2->anonymous);
$event3 = \core_tests\event\unittest_executed::create(array('contextid'=>$system->id, 'objectid'=>5, 'anonymous'=>true, 'other'=>array('sample'=>null, 'xx'=>10)));
$this->assertSame(1, $event3->anonymous);
}
public function test_event_properties_guessing(): void {
global $USER;
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
$context = \context_module::instance($forum->cmid);
$event = \core_tests\event\unittest_executed::create(array('context' => $context, 'objectid' => 5));
// Check guessed course ID, and default properties.
$this->assertSame('\core_tests\event\unittest_executed', $event->eventname);
$this->assertSame('core_tests', $event->component);
$this->assertSame('executed', $event->action);
$this->assertSame('unittest', $event->target);
$this->assertSame(5, $event->objectid);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($course->id, $event->courseid);
$this->assertSame($USER->id, $event->userid);
$this->assertNull($event->relateduserid);
$user = $this->getDataGenerator()->create_user();
$context = \context_user::instance($user->id);
$event = \core_tests\event\unittest_executed::create(array('contextid' => $context->id, 'objectid' => 5));
// Check guessing on contextid, and user context level.
$this->assertEquals($context, $event->get_context());
$this->assertEquals($context->id, $event->contextid);
$this->assertEquals($context->contextlevel, $event->contextlevel);
$this->assertSame(0, $event->courseid);
$this->assertSame($USER->id, $event->userid);
$this->assertSame($user->id, $event->relateduserid);
}
public function test_observers_parsing(): void {
global $CFG;
$observers = array(
array(
'eventname' => '*',
'callback' => array('\core_tests\event\unittest_observer', 'observe_all_alt'),
),
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::observe_one',
'includefile' => 'lib/tests/fixtures/event_fixtures.php',
),
array(
'eventname' => '*',
'callback' => array('\core_tests\event\unittest_observer', 'observe_all'),
'includefile' => null,
'internal' => 1,
'priority' => 10,
),
array(
'eventname' => '\core\event\unknown_executed',
'callback' => '\core_tests\event\unittest_observer::broken_observer',
'priority' => 100,
),
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::external_observer',
'priority' => 200,
'internal' => 0,
),
);
$result = \core\event\manager::phpunit_replace_observers($observers);
$this->assertCount(3, $result);
$expected = array();
$observer = new \stdClass();
$observer->callable = '\core_tests\event\unittest_observer::external_observer';
$observer->priority = 200;
$observer->internal = false;
$observer->includefile = null;
$observer->plugintype = null;
$observer->plugin = null;
$expected[0] = $observer;
$observer = new \stdClass();
$observer->callable = '\core_tests\event\unittest_observer::observe_one';
$observer->priority = 0;
$observer->internal = true;
$observer->includefile = $CFG->dirroot.'/lib/tests/fixtures/event_fixtures.php';
$observer->plugintype = null;
$observer->plugin = null;
$expected[1] = $observer;
$this->assertEquals($expected, $result['\core_tests\event\unittest_executed']);
$expected = array();
$observer = new \stdClass();
$observer->callable = '\core_tests\event\unittest_observer::broken_observer';
$observer->priority = 100;
$observer->internal = true;
$observer->includefile = null;
$observer->plugintype = null;
$observer->plugin = null;
$expected[0] = $observer;
$this->assertEquals($expected, $result['\core\event\unknown_executed']);
$expected = array();
$observer = new \stdClass();
$observer->callable = array('\core_tests\event\unittest_observer', 'observe_all');
$observer->priority = 10;
$observer->internal = true;
$observer->includefile = null;
$observer->plugintype = null;
$observer->plugin = null;
$expected[0] = $observer;
$observer = new \stdClass();
$observer->callable = array('\core_tests\event\unittest_observer', 'observe_all_alt');
$observer->priority = 0;
$observer->internal = true;
$observer->includefile = null;
$observer->plugintype = null;
$observer->plugin = null;
$expected[1] = $observer;
$this->assertEquals($expected, $result['\core\event\base']);
// Now test broken stuff...
$observers = array(
array(
'eventname' => 'core_tests\event\unittest_executed', // Fix leading backslash.
'callback' => '\core_tests\event\unittest_observer::observe_one',
'includefile' => 'lib/tests/fixtures/event_fixtures.php',
'internal' => 1, // Cast to bool.
),
);
$result = \core\event\manager::phpunit_replace_observers($observers);
$this->assertCount(1, $result);
$expected = array();
$observer = new \stdClass();
$observer->callable = '\core_tests\event\unittest_observer::observe_one';
$observer->priority = 0;
$observer->internal = true;
$observer->includefile = $CFG->dirroot.'/lib/tests/fixtures/event_fixtures.php';
$observer->plugintype = null;
$observer->plugin = null;
$expected[0] = $observer;
$this->assertEquals($expected, $result['\core_tests\event\unittest_executed']);
$observers = array(
array(
// Missing eventclass.
'callback' => '\core_tests\event\unittest_observer::observe_one',
'includefile' => 'lib/tests/fixtures/event_fixtures.php',
),
);
$result = \core\event\manager::phpunit_replace_observers($observers);
$this->assertCount(0, $result);
$this->assertDebuggingCalled();
$observers = array(
array(
'eventname' => '', // Empty eventclass.
'callback' => '\core_tests\event\unittest_observer::observe_one',
'includefile' => 'lib/tests/fixtures/event_fixtures.php',
),
);
$result = \core\event\manager::phpunit_replace_observers($observers);
$this->assertCount(0, $result);
$this->assertDebuggingCalled();
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
// Missing callable.
'includefile' => 'lib/tests/fixtures/event_fixtures.php',
),
);
$result = \core\event\manager::phpunit_replace_observers($observers);
$this->assertCount(0, $result);
$this->assertDebuggingCalled();
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '', // Empty callable.
'includefile' => 'lib/tests/fixtures/event_fixtures.php',
),
);
$result = \core\event\manager::phpunit_replace_observers($observers);
$this->assertCount(0, $result);
$this->assertDebuggingCalled();
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::observe_one',
'includefile' => 'lib/tests/fixtures/event_fixtures.php_xxx', // Missing file.
),
);
$result = \core\event\manager::phpunit_replace_observers($observers);
$this->assertCount(0, $result);
$this->assertDebuggingCalled();
}
public function test_normal_dispatching(): void {
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::observe_one',
),
array(
'eventname' => '*',
'callback' => '\core_tests\event\unittest_observer::observe_all',
'includefile' => null,
'internal' => 1,
'priority' => 9999,
),
);
\core\event\manager::phpunit_replace_observers($observers);
\core_tests\event\unittest_observer::reset();
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$event1->nest = 1;
$this->assertFalse($event1->is_triggered());
$this->assertFalse($event1->is_dispatched());
$this->assertFalse($event1->is_restored());
$event1->trigger();
$this->assertTrue($event1->is_triggered());
$this->assertTrue($event1->is_dispatched());
$this->assertFalse($event1->is_restored());
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
$event1->trigger();
$this->assertSame(
array('observe_all-nesting-1', 'observe_one-1', 'observe_all-666', 'observe_one-666', 'observe_all-2', 'observe_one-2'),
\core_tests\event\unittest_observer::$info);
}
public function test_event_sink(): void {
$sink = $this->redirectEvents();
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$event1->trigger();
$this->assertSame(1, $sink->count());
$retult = $sink->get_events();
$this->assertSame($event1, $retult[0]);
$event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
$event2->trigger();
$this->assertSame(2, $sink->count());
$retult = $sink->get_events();
$this->assertSame($event1, $retult[0]);
$this->assertSame($event2, $retult[1]);
$sink->clear();
$this->assertSame(0, $sink->count());
$this->assertSame(array(), $sink->get_events());
$event3 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>3, 'xx'=>10)));
$event3->trigger();
$this->assertSame(1, $sink->count());
$retult = $sink->get_events();
$this->assertSame($event3, $retult[0]);
$sink->close();
$event4 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>4, 'xx'=>10)));
$event4->trigger();
$this->assertSame(1, $sink->count());
$retult = $sink->get_events();
$this->assertSame($event3, $retult[0]);
}
public function test_ignore_exceptions(): void {
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::observe_one',
),
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::broken_observer',
'priority' => 100,
),
);
\core\event\manager::phpunit_replace_observers($observers);
\core_tests\event\unittest_observer::reset();
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$event1->trigger();
$this->assertDebuggingCalled();
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
$event1->trigger();
$this->assertDebuggingCalled();
$this->assertSame(
array('broken_observer-1', 'observe_one-1', 'broken_observer-2', 'observe_one-2'),
\core_tests\event\unittest_observer::$info);
}
public function test_external_buffer(): void {
global $DB;
$this->preventResetByRollback();
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::observe_one',
),
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::external_observer',
'priority' => 200,
'internal' => 0,
),
);
\core\event\manager::phpunit_replace_observers($observers);
\core_tests\event\unittest_observer::reset();
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$event1->trigger();
$event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
$event2->trigger();
$this->assertSame(
array('external_observer-1', 'observe_one-1', 'external_observer-2', 'observe_one-2'),
\core_tests\event\unittest_observer::$info);
\core\event\manager::phpunit_replace_observers($observers);
\core_tests\event\unittest_observer::reset();
$this->assertSame(array(), \core_tests\event\unittest_observer::$info);
$trans = $DB->start_delegated_transaction();
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$event1->trigger();
$event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
$event2->trigger();
$this->assertSame(
array('observe_one-1', 'observe_one-2'),
\core_tests\event\unittest_observer::$info);
$trans->allow_commit();
$this->assertSame(
array('observe_one-1', 'observe_one-2', 'external_observer-1', 'external_observer-2'),
\core_tests\event\unittest_observer::$info);
\core\event\manager::phpunit_replace_observers($observers);
\core_tests\event\unittest_observer::reset();
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$event1->trigger();
$trans = $DB->start_delegated_transaction();
$event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
$event2->trigger();
try {
$trans->rollback(new \moodle_exception('xxx'));
$this->fail('Expecting exception');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\moodle_exception::class, $e);
}
$this->assertSame(
array('external_observer-1', 'observe_one-1', 'observe_one-2'),
\core_tests\event\unittest_observer::$info);
}
public function test_rollback(): void {
global $DB;
$this->resetAfterTest();
$this->preventResetByRollback();
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::external_observer',
'internal' => 0,
),
);
\core\event\manager::phpunit_replace_observers($observers);
\core_tests\event\unittest_observer::reset();
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
\core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
$this->assertCount(1, \core_tests\event\unittest_observer::$event);
\core_tests\event\unittest_observer::reset();
$transaction1 = $DB->start_delegated_transaction();
\core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
$transaction2 = $DB->start_delegated_transaction();
\core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
try {
$transaction2->rollback(new \Exception('x'));
$this->fail('Expecting exception');
} catch (\Exception $e) {}
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
$this->assertTrue($DB->is_transaction_started());
try {
$transaction1->rollback(new \Exception('x'));
$this->fail('Expecting exception');
} catch (\Exception $e) {}
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
$this->assertFalse($DB->is_transaction_started());
\core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
$this->assertCount(1, \core_tests\event\unittest_observer::$event);
}
public function test_forced_rollback(): void {
global $DB;
$this->resetAfterTest();
$this->preventResetByRollback();
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::external_observer',
'internal' => 0,
),
);
\core\event\manager::phpunit_replace_observers($observers);
\core_tests\event\unittest_observer::reset();
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
\core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
$this->assertCount(1, \core_tests\event\unittest_observer::$event);
\core_tests\event\unittest_observer::reset();
$transaction1 = $DB->start_delegated_transaction();
\core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
$transaction2 = $DB->start_delegated_transaction();
\core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
$DB->force_transaction_rollback();
$this->assertCount(0, \core_tests\event\unittest_observer::$event);
$this->assertFalse($DB->is_transaction_started());
\core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
$this->assertCount(1, \core_tests\event\unittest_observer::$event);
}
public function test_deprecated(): void {
global $DB;
$this->resetAfterTest(true);
$event = \core_tests\event\deprecated_event1::create();
$this->assertDebuggingCalled('level property is deprecated, use edulevel property instead');
$this->assertSame($event::LEVEL_TEACHING, $event->level);
$this->assertDebuggingCalled('level property is deprecated, use edulevel property instead');
$this->assertTrue(isset($event->level));
$this->assertDebuggingCalled('level property is deprecated, use edulevel property instead');
$this->assertSame($event::LEVEL_TEACHING, $event->edulevel);
}
public function test_legacy(): void {
global $DB, $CFG;
$this->resetAfterTest(true);
$observers = array(
array(
'eventname' => '\core_tests\event\unittest_executed',
'callback' => '\core_tests\event\unittest_observer::observe_one',
),
array(
'eventname' => '*',
'callback' => '\core_tests\event\unittest_observer::observe_all',
'includefile' => null,
'internal' => 1,
'priority' => 9999,
),
);
$DB->delete_records('log', array());
$this->expectException(\coding_exception::class);
events_update_definition('unittest');
$DB->delete_records_select('events_handlers', "component <> 'unittest'");
$this->assertDebuggingCalled(self::DEBUGGING_MSG, DEBUG_DEVELOPER);
$this->assertEquals(3, $DB->count_records('events_handlers'));
set_config('loglifetime', 60*60*24*5);
\core\event\manager::phpunit_replace_observers($observers);
\core_tests\event\unittest_observer::reset();
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>5, 'xx'=>10)));
$event1->trigger();
$event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>6, 'xx'=>11)));
$event2->nest = true;
$event2->trigger();
$this->assertSame(
array('observe_all-5', 'observe_one-5', 'observe_all-nesting-6', 'observe_one-6', 'observe_all-666', 'observe_one-666'),
\core_tests\event\unittest_observer::$info);
$this->assertSame($event1, \core_tests\event\unittest_observer::$event[0]);
$this->assertSame($event1, \core_tests\event\unittest_observer::$event[1]);
$logs = $DB->get_records('log', array(), 'id ASC');
$this->assertCount(0, $logs);
}
public function test_restore_event(): void {
$event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$data1 = $event1->get_data();
$event2 = \core\event\base::restore($data1, array('origin'=>'clid'));
$data2 = $event2->get_data();
$this->assertTrue($event2->is_triggered());
$this->assertTrue($event2->is_restored());
$this->assertEquals($data1, $data2);
$this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event2);
$this->assertEquals($event1->get_context(), $event2->get_context());
// Now test problematic data.
$data3 = $data1;
$data3['eventname'] = '\\a\\b\\c';
$event3 = \core\event\base::restore($data3, array());
$this->assertFalse($event3, 'Class name must match');
$data4 = $data1;
unset($data4['userid']);
$event4 = \core\event\base::restore($data4, array());
$this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event4);
$this->assertDebuggingCalled();
$data5 = $data1;
$data5['xx'] = 'xx';
$event5 = \core\event\base::restore($data5, array());
$this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event5);
$this->assertDebuggingCalled();
}
public function test_trigger_problems(): void {
$this->resetAfterTest(true);
$event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>5, 'xx'=>10)));
$event->trigger();
try {
$event->trigger();
$this->fail('Exception expected on double trigger');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
$data = $event->get_data();
$restored = \core_tests\event\unittest_executed::restore($data, array());
$this->assertTrue($restored->is_triggered());
$this->assertTrue($restored->is_restored());
try {
$restored->trigger();
$this->fail('Exception expected on triggering of restored event');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
$event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>5, 'xx'=>10)));
try {
\core\event\manager::dispatch($event);
$this->fail('Exception expected on manual event dispatching');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
}
public function test_bad_events(): void {
$this->resetAfterTest(true);
try {
$event = \core_tests\event\unittest_executed::create(array('other'=>array('sample'=>5, 'xx'=>10)));
$this->fail('Exception expected when context and contextid missing');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
$event = \core_tests\event\bad_event1::create(array('context'=>\context_system::instance()));
try {
$event->trigger();
$this->fail('Exception expected when $data not valid');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
$event = \core_tests\event\bad_event2::create(array('context'=>\context_system::instance()));
try {
$event->trigger();
$this->fail('Exception expected when $data not valid');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
$event = \core_tests\event\bad_event2b::create(array('context'=>\context_system::instance()));
@$event->trigger();
$this->assertDebuggingCalled();
$event = \core_tests\event\bad_event3::create(array('context'=>\context_system::instance()));
@$event->trigger();
$this->assertDebuggingCalled();
$event = \core_tests\event\bad_event4::create(array('context'=>\context_system::instance()));
@$event->trigger();
$this->assertDebuggingCalled();
$event = \core_tests\event\bad_event5::create(array('context'=>\context_system::instance()));
@$event->trigger();
$this->assertDebuggingCalled();
$event = \core_tests\event\bad_event6::create(array('objectid'=>1, 'context'=>\context_system::instance()));
$event->trigger();
$this->assertDebuggingCalled('Unknown table specified in objecttable field');
$event = \core_tests\event\bad_event7::create(array('objectid'=>1, 'context'=>\context_system::instance()));
try {
$event->trigger();
$this->fail('Exception expected when $data contains objectid but objecttable not specified');
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
$event = \core_tests\event\bad_event8::create(array('context'=>\context_system::instance()));
$event->trigger();
$this->assertDebuggingCalled('Event property objectid must be set when objecttable is defined');
}
public function test_problematic_events(): void {
$this->resetAfterTest(true);
$event1 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance()));
$this->assertDebuggingNotCalled();
$this->assertNull($event1->xxx);
$this->assertDebuggingCalled();
$event2 = \core_tests\event\problematic_event1::create(array('xxx'=>0, 'context'=>\context_system::instance()));
$this->assertDebuggingCalled();
set_debugging(DEBUG_NONE);
$event3 = \core_tests\event\problematic_event1::create(array('xxx'=>0, 'context'=>\context_system::instance()));
$this->assertDebuggingNotCalled();
set_debugging(DEBUG_DEVELOPER);
$event4 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance(), 'other'=>array('a'=>1)));
$event4->trigger();
$this->assertDebuggingNotCalled();
// Check the invalid content that cannot be converted to JSON will trigger debugging messages.
$event5 = \core_tests\event\problematic_event1::create(array('context' => \context_system::instance(), 'other' => [
'a' => NAN
]));
$this->assertDebuggingNotCalled();
$event5->trigger();
$this->assertDebuggingCalled();
// Check that moodle_url object does not trigger debugging messages.
$url = new \moodle_url('/admin/');
$event6 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance(), 'other'=>array('a'=>$url)));
$event6->trigger();
$this->assertDebuggingNotCalled();
// Check that whole float numbers do not trigger debugging messages.
$event7 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(),
'other' => array('wholenumber' => 90.0000, 'numberwithdecimals' => 54.7656, 'sample' => 1)));
$event7->trigger();
$this->assertDebuggingNotCalled();
$event = \core_tests\event\problematic_event2::create(array());
$this->assertDebuggingNotCalled();
$event = \core_tests\event\problematic_event2::create(array('context'=>\context_system::instance()));
$this->assertDebuggingCalled();
$event = \core_tests\event\problematic_event3::create(array('other'=>1));
$this->assertDebuggingNotCalled();
$event = \core_tests\event\problematic_event3::create(array());
$this->assertDebuggingCalled();
}
public function test_record_snapshots(): void {
global $DB;
$this->resetAfterTest(true);
$event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$course1 = $DB->get_record('course', array('id'=>1));
$this->assertNotEmpty($course1);
$event->add_record_snapshot('course', $course1);
$result = $event->get_record_snapshot('course', $course1->id);
// Convert to arrays because record snapshot returns a clone of the object.
$this->assertSame((array)$course1, (array)$result);
$user = $event->get_record_snapshot('user', 1);
$this->assertEquals(1, $user->id);
$this->assertSame('guest', $user->username);
$event->add_record_snapshot('course', $course1);
$event->trigger();
try {
$event->add_record_snapshot('course', $course1);
$this->fail('Updating of snapshots after trigger is not ok');;
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
$event2 = \core_tests\event\unittest_executed::restore($event->get_data(), array());
try {
$event2->get_record_snapshot('course', $course1->id);
$this->fail('Reading of snapshots from restored events is not ok');;
} catch (\moodle_exception $e) {
$this->assertInstanceOf(\coding_exception::class, $e);
}
}
public function test_get_name(): void {
$event = \core_tests\event\noname_event::create(array('other' => array('sample' => 1, 'xx' => 10)));
$this->assertEquals("core_tests: noname event", $event->get_name());
}
public function test_iteration(): void {
$event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
$data = array();
foreach ($event as $k => $v) {
$data[$k] = $v;
}
$this->assertSame($event->get_data(), $data);
}
/**
* Test that all observer information is returned correctly.
*/
public function test_get_all_observers(): void {
// Retrieve all observers.
$observers = \core\event\manager::get_all_observers();
// Expected information from the workshop allocation scheduled observer.
$expected = new \stdClass();
$expected->callable = '\workshopallocation_scheduled\observer::workshop_viewed';
$expected->priority = 0;
$expected->internal = true;
$expected->includefile = null;
$expected->plugintype = 'workshopallocation';
$expected->plugin = 'scheduled';
// May be more than one observer for the mod_workshop event.
$found = false;
foreach ($observers['\mod_workshop\event\course_module_viewed'] as $observer) {
if ($expected == $observer) {
$found = true;
break;
}
}
$this->assertTrue($found);
}
/**
* Test formatting of the get_explanation method.
* This formats the information from an events class docblock.
*/
public function test_get_explanation(): void {
$explanation = \core_tests\event\full_docblock::get_explanation();
$expected = "This is an explanation of the event.
- I'm making a point here.
- I have a second {@link something} point here.
- whitespace is intentional to test it's removal.
I have something else *Yeah* that.";
$this->assertEquals($explanation, $expected);
$explanation = \core_tests\event\docblock_test2::get_explanation();
$expected = "We have only the description in the docblock
and nothing else.";
$this->assertEquals($explanation, $expected);
$explanation = \core_tests\event\docblock_test3::get_explanation();
$expected = "Calendar event created event.";
$this->assertEquals($explanation, $expected);
}
/**
* Test that general information about an event is returned
* by the get_static_info() method.
*/
public function test_get_static_info(): void {
$staticinfo = \core_tests\event\static_info_viewing::get_static_info();
$expected = array(
'eventname' => '\\core_tests\\event\\static_info_viewing',
'component' => 'core_tests',
'target' => 'static_info',
'action' => 'viewing',
'crud' => 'r',
'edulevel' => 0,
'objecttable' => 'mod_unittest'
);
$this->assertEquals($staticinfo, $expected);
}
/**
* This tests the internal method of \core\event\manager::get_observing_classes.
*
* What we are testing is if we can subscribe to a parent event class, instead of only
* the base event class or the final, implemented event class. This enables us to subscribe
* to things like all course module view events, all comment created events, etc.
*/
public function test_observe_parent_event(): void {
$this->resetAfterTest();
// Ensure this has been reset prior to using it.
\core_tests\event\unittest_observer::reset();
$course = $this->getDataGenerator()->create_course();
$feed = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
$context = \context_module::instance($feed->cmid);
$data = [
'context' => $context,
'courseid' => $course->id,
'objectid' => $feed->id
];
// This assertion ensures that basic observe use case did not break.
\core\event\manager::phpunit_replace_observers([[
'eventname' => '\core_tests\event\course_module_viewed',
'callback' => ['\core_tests\event\unittest_observer', 'observe_all_alt'],
]]);
$pageevent = \core_tests\event\course_module_viewed::create($data);
$pageevent->trigger();
$this->assertSame(['observe_all_alt'], \core_tests\event\unittest_observer::$info, 'Error observing triggered event');
\core_tests\event\unittest_observer::reset();
// This assertion tests that we can observe an abstract (parent) class instead of the implemented class.
\core\event\manager::phpunit_replace_observers([[
'eventname' => '\core\event\course_module_viewed',
'callback' => ['\core_tests\event\unittest_observer', 'observe_all_alt'],
]]);
$pageevent = \core_tests\event\course_module_viewed::create($data);
$pageevent->trigger();
$this->assertSame(['observe_all_alt'], \core_tests\event\unittest_observer::$info, 'Error observing parent class event');
\core_tests\event\unittest_observer::reset();
}
}
@@ -0,0 +1,78 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Content bank created event tests.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
/**
* Test for content bank created event.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\event\contentbank_content_created
*/
class contentbank_content_created_test extends \advanced_testcase {
/**
* Setup to ensure that fixtures are loaded.
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
}
/**
* Test the content created event.
*
* @covers ::create_from_record
*/
public function test_content_created(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Save the system context.
$systemcontext = \context_system::instance();
// Trigger and capture the event when creating a content.
$sink = $this->redirectEvents();
// Create a content bank content.
/** @var \core_contentbank_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
$contents = $generator->generate_contentbank_data('contenttype_testable', 1);
$content = array_shift($contents);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\contentbank_content_created', $event);
$this->assertEquals($systemcontext, $event->get_context());
}
}
@@ -0,0 +1,84 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Content bank deleted event tests.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
/**
* Test for content bank deleted event.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\event\contentbank_content_deleted
*/
class contentbank_content_deleted_test extends \advanced_testcase {
/**
* Setup to ensure that fixtures are loaded.
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
}
/**
* Test the content deleted event
*
* @covers ::create_from_record
*/
public function test_content_deleted(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Save the system context.
$systemcontext = \context_system::instance();
// Create a content bank content.
/** @var \core_contentbank_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
$contents = $generator->generate_contentbank_data('contenttype_testable', 3);
$content = array_shift($contents);
$this->assertEquals(3, $DB->count_records('contentbank_content'));
$classname = '\\contenttype_testable\\contenttype';
$contentype = new $classname($systemcontext);
// Trigger and capture the event for deleting a content.
$sink = $this->redirectEvents();
$contentype->delete_content($content);
$events = $sink->get_events();
$event = reset($events);
// Check that the content was deleted and the event data is valid.
$this->assertEquals(2, $DB->count_records('contentbank_content'));
$this->assertInstanceOf('\core\event\contentbank_content_deleted', $event);
$this->assertEquals(\context_system::instance(), $event->get_context());
}
}
@@ -0,0 +1,83 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Content bank updated event tests.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
/**
* Test for content bank updated event.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\event\contentbank_content_updated
*/
class contentbank_content_updated_test extends \advanced_testcase {
/**
* Setup to ensure that fixtures are loaded.
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
}
/**
* Test the content updated event.
*
* @covers ::create_from_record
*/
public function test_content_updated(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Save the system context.
$systemcontext = \context_system::instance();
// Create a content bank content.
/** @var \core_contentbank_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
$contents = $generator->generate_contentbank_data('contenttype_testable', 1);
$content = array_shift($contents);
// Store the name before we change it.
$oldname = $content->get_name();
// Trigger and capture the event when renaming a content.
$sink = $this->redirectEvents();
$newname = "New name";
$content->set_name($newname);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\contentbank_content_updated', $event);
$this->assertEquals($systemcontext, $event->get_context());
}
}
@@ -0,0 +1,94 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Content bank uploaded event tests.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
use core_contentbank\contentbank;
/**
* Test for content bank uploaded event.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\event\contentbank_content_uploaded
*/
class contentbank_content_uploaded_test extends \advanced_testcase {
/**
* Setup to ensure that fixtures are loaded.
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
}
/**
* Test the content created event.
*
* @covers ::create_from_record
*/
public function test_content_created(): void {
global $USER, $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$systemcontext = \context_system::instance();
// Create a dummy H5P file.
$dummyh5p = array(
'contextid' => $systemcontext->id,
'component' => 'contentbank',
'filearea' => 'public',
'itemid' => 1,
'filepath' => '/',
'filename' => 'dummy_h5p.h5p'
);
$path = $CFG->dirroot . '/h5p/tests/fixtures/greeting-card.h5p';
$dummyh5pfile = \core_h5p\helper::create_fake_stored_file_from_path($path);
// Trigger and capture the event when creating content from a file.
$sink = $this->redirectEvents();
$cb = new contentbank();
$cb->create_content_from_file($systemcontext, $USER->id, $dummyh5pfile);
// Both uploaded and created events are raised.
$events = $sink->get_events();
$this->assertCount(2, $events);
// First the created content event has been raised.
$event = array_shift($events);
$this->assertInstanceOf('\core\event\contentbank_content_created', $event);
$this->assertEquals($systemcontext, $event->get_context());
// Second the uploaded content event has been raised.
$event = array_pop($events);
$this->assertInstanceOf('\core\event\contentbank_content_uploaded', $event);
$this->assertEquals($systemcontext, $event->get_context());
}
}
@@ -0,0 +1,82 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Content bank viewed event tests.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
/**
* Test for content bank viewed event.
*
* @package core
* @category test
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\event\contentbank_content_viewed
*/
class contentbank_content_viewed_test extends \advanced_testcase {
/**
* Setup to ensure that fixtures are loaded.
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
}
/**
* Test the content viewed event.
*
* @covers ::create_from_record
*/
public function test_content_viewed(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Save the system context.
$systemcontext = \context_system::instance();
$contenttype = new \contenttype_testable\contenttype();
// Create a content bank content.
/** @var \core_contentbank_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
$contents = $generator->generate_contentbank_data('contenttype_testable', 1);
$content = array_shift($contents);
// Trigger and capture the content viewed event.
$sink = $this->redirectEvents();
$result = $contenttype->get_view_content($content);
$this->assertEmpty($result);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\contentbank_content_viewed', $event);
$this->assertEquals($systemcontext, $event->get_context());
$this->assertEquals($content->get_id(), $event->objectid);
}
}
+97
View File
@@ -0,0 +1,97 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
/**
* Unit tests for the context_locked and context_unlocked events.
*
* @package core
* @category test
* @copyright 2019 University of Nottingham
* @author Neill Magill <neill.magill@nottingham.ac.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class context_locked_test extends \advanced_testcase {
/**
* Locks an unlocked context and checks that a core\event\context_locked event is created.
*
* @param \context $context
*/
protected function lock_context(\context $context) {
self::assertFalse($context->is_locked());
$locksink = $this->redirectEvents();
$context->set_locked(true);
// This second call should not create an event as the lock status has not changed.
$context->set_locked(true);
$lockevents = $locksink->get_events();
$locksink->close();
self::assertCount(1, $lockevents);
self::assertContainsOnlyInstancesOf(context_locked::class, $lockevents);
self::assertEquals($context->id, $lockevents[0]->objectid);
$this->assertSame('context', $lockevents[0]->objecttable);
$this->assertEquals($context, $lockevents[0]->get_context());
}
/**
* Tests that events are created when contexts are locked and unlocked.
*/
public function test_creation(): void {
$this->resetAfterTest();
$category = self::getDataGenerator()->create_category();
$catcontext = \context_coursecat::instance($category->id);
$course = self::getDataGenerator()->create_course(['category' => $category->id]);
$coursecontext = \context_course::instance($course->id);
/** @var \mod_forum_generator $activitygenerator */
$activitygenerator = self::getDataGenerator()->get_plugin_generator('mod_forum');
$activity = $activitygenerator->create_instance(['course' => $course->id]);
$activitycontext = \context_module::instance($activity->cmid);
$this->lock_context($catcontext);
$this->unlock_context($catcontext);
$this->lock_context($coursecontext);
$this->unlock_context($coursecontext);
$this->lock_context($activitycontext);
$this->unlock_context($activitycontext);
}
/**
* Unlocks a locked context and checks that a core\event\context_unlocked event is created.
*
* @param \context $context
*/
protected function unlock_context(\context $context) {
self::assertTrue($context->is_locked());
$unlocksink = $this->redirectEvents();
$context->set_locked(false);
// This second call should not create an event as the lock status has not changed.
$context->set_locked(false);
$unlockevents = $unlocksink->get_events();
$unlocksink->close();
self::assertCount(1, $unlockevents);
self::assertContainsOnlyInstancesOf(context_unlocked::class, $unlockevents);
self::assertEquals($context->id, $unlockevents[0]->objectid);
$this->assertSame('context', $unlockevents[0]->objecttable);
$this->assertEquals($context, $unlockevents[0]->get_context());
}
}
@@ -0,0 +1,77 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
use advanced_testcase;
use context_course;
use context_system;
use Exception;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/../fixtures/event_mod_fixtures.php');
/**
* Tests for base course module instance list viewed event.
*
* @package core
* @category phpunit
* @covers \core\event\course_module_instance_list_viewed
* @copyright 2013 Ankit Agarwal
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class course_module_instance_list_viewed_test extends advanced_testcase {
/**
* Test event properties and methods.
*/
public function test_event_attributes() {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$context = context_course::instance($course->id);
// Trigger the page view event.
$sink = $this->redirectEvents();
$event = \mod_unittests\event\course_module_instance_list_viewed::create(array(
'context' => $context,
));
$event->trigger();
$result = $sink->get_events();
$event = reset($result);
$sink->close();
// Test event data.
$url = new moodle_url('/mod/unittests/index.php', array('id' => $course->id));
$this->assertEquals($url, $event->get_url());
$this->assertEventContextNotUsed($event);
}
/**
* Test custom validations of the event.
*/
public function test_event_validations() {
try {
\mod_unittests\event\course_module_instance_list_viewed::create(array('context' => context_system::instance()));
$this->fail('Event validation should not allow course_module_instance_list_viewed event to be triggered without outside
course context');
} catch (Exception $e) {
$this->assertInstanceOf('coding_exception', $e);
}
}
}
@@ -0,0 +1,100 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
use advanced_testcase;
use coding_exception;
use context_module;
use stdClass;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/../fixtures/event_fixtures.php');
/**
* Tests for base course module viewed event.
*
* @package core
* @category phpunit
* @covers \core\event\course_module_viewed
* @copyright 2013 Ankit Agarwal
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class course_module_viewed_test extends advanced_testcase {
/**
* Test event properties and methods.
*/
public function test_event_attributes() {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$record = new stdClass();
$record->course = $course->id;
$feed = $this->getDataGenerator()->create_module('feedback', $record);
$cm = get_coursemodule_from_instance('feedback', $feed->id);
$context = context_module::instance($cm->id);
// Trigger the page view event.
$sink = $this->redirectEvents();
$pageevent = \core_tests\event\course_module_viewed::create(array(
'context' => $context,
'courseid' => $course->id,
'objectid' => $feed->id
));
$pageevent->trigger();
$result = $sink->get_events();
$event = reset($result);
$sink->close();
$this->assertSame('feedback', $event->objecttable);
$url = new moodle_url('/mod/feedback/view.php', array('id' => $cm->id));
$this->assertEquals($url, $event->get_url());
$this->assertEventContextNotUsed($event);
}
/**
* Test custom validations of the event.
*/
public function test_event_validations() {
// Make sure objecttable and object id is always set.
try {
\core_tests\event\course_module_viewed_noinit::create(array(
'contextid' => 1,
'courseid' => 2,
'objectid' => 3 ));
} catch (coding_exception $e) {
$this->assertStringContainsString("course_module_viewed event must define objectid and object table.", $e->getMessage());
}
$this->assertDebuggingCalled('Inconsistent courseid - context combination detected.');
$this->resetDebugging();
try {
\core_tests\event\course_module_viewed::create(array(
'contextid' => 1,
'courseid' => 2,
));
} catch (coding_exception $e) {
$this->assertStringContainsString("course_module_viewed event must define objectid and object table.", $e->getMessage());
}
$this->assertDebuggingCalled('Inconsistent courseid - context combination detected.');
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
/**
* Tests for deprecated events.
*
* @package core
* @category test
* @copyright 2013 onwards Ankit Agarwal
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class deprecated_test extends \advanced_testcase {
/**
* Test event properties and methods.
*/
public function test_deprecated_course_module_instances_list_viewed_events(): void {
// Make sure the abstract class course_module_instances_list_viewed generates a debugging notice.
require_once(__DIR__ . '/../fixtures/event_mod_badfixtures.php');
$this->assertDebuggingCalled(null, DEBUG_DEVELOPER);
}
}
+86
View File
@@ -0,0 +1,86 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* File added to draft area test events.
*
* @package core
* @category test
* @copyright 2023 The Open University.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
/**
* Test for draft file added event.
*
* @package core
* @category test
* @copyright 2023 The Open University.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core\event\draft_file_added
*/
class draft_file_added_test extends \advanced_testcase {
/**
* Test draft file added event.
*/
public function test_event(): void {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$usercontext = \context_user::instance($user->id);
$sink = $this->redirectEvents();
$fs = get_file_storage();
$filerecord = [
'contextid' => $usercontext->id,
'component' => 'core',
'filearea' => 'unittest',
'itemid' => 0,
'filepath' => '/',
'filename' => 'test.txt',
'source' => 'Copyright stuff',
];
$originalfile = $fs->create_file_from_string($filerecord, 'Test content');
$nbsp = "\xc2\xa0";
// Event data for logging.
$eventdata = [
'objectid' => $originalfile->get_id(),
'context' => $usercontext,
'other' => [
'itemid' => $originalfile->get_itemid(),
'filename' => $originalfile->get_filename(),
'filesize' => $originalfile->get_filesize(),
'filepath' => $originalfile->get_filepath(),
'contenthash' => $originalfile->get_contenthash(),
]
];
$event = \core\event\draft_file_added::create($eventdata);
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
$this->assertEquals($usercontext, $event->get_context());
$expected = "The user with id '{$user->id}' has uploaded file '/test.txt' to the draft file area with item id 0. ".
"Size: 12{$nbsp}bytes. Content hash: {$originalfile->get_contenthash()}.";
$this->assertSame($expected, $event->get_description());
}
}
@@ -0,0 +1,86 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* File deleted from draft area test events.
*
* @package core
* @category test
* @copyright 2023 The Open University.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
/**
* Test for draft file deleted event.
*
* @package core
* @category test
* @copyright 2023 The Open University.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core\event\draft_file_deleted
*/
class draft_file_deleted_test extends \advanced_testcase {
/**
* Test draft file deleted event.
*/
public function test_event(): void {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$usercontext = \context_user::instance($user->id);
$sink = $this->redirectEvents();
$fs = get_file_storage();
$filerecord = [
'contextid' => $usercontext->id,
'component' => 'core',
'filearea' => 'unittest',
'itemid' => 0,
'filepath' => '/',
'filename' => 'test.txt',
'source' => 'Copyright stuff',
];
$originalfile = $fs->create_file_from_string($filerecord, 'Test content');
$nbsp = "\xc2\xa0";
// Event data for logging.
$eventdata = [
'objectid' => $originalfile->get_id(),
'context' => $usercontext,
'other' => [
'itemid' => $originalfile->get_itemid(),
'filename' => $originalfile->get_filename(),
'filesize' => $originalfile->get_filesize(),
'filepath' => $originalfile->get_filepath(),
'contenthash' => $originalfile->get_contenthash(),
],
];
$event = \core\event\draft_file_deleted::create($eventdata);
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
$this->assertEquals($usercontext, $event->get_context());
$expected = "The user with id '{$user->id}' has deleted file '/test.txt' from the draft file area with item id 0. " .
"Size: 12{$nbsp}bytes. Content hash: {$originalfile->get_contenthash()}.";
$this->assertSame($expected, $event->get_description());
}
}
+369
View File
@@ -0,0 +1,369 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Events tests.
*
* @package core
* @category test
* @copyright 2014 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/../fixtures/event_fixtures.php');
class events_test extends \advanced_testcase {
/**
* Test set up.
*
* This is executed before running any test in this file.
*/
public function setUp(): void {
$this->resetAfterTest();
}
/**
* Test the course category created event.
*/
public function test_course_category_created(): void {
// Trigger and capture the event.
$sink = $this->redirectEvents();
$category = $this->getDataGenerator()->create_category();
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\course_category_created', $event);
$this->assertEquals(\context_coursecat::instance($category->id), $event->get_context());
$url = new \moodle_url('/course/management.php', array('categoryid' => $event->objectid));
$this->assertEquals($url, $event->get_url());
$this->assertEventContextNotUsed($event);
}
/**
* Test the course category updated event.
*/
public function test_course_category_updated(): void {
// Create a category.
$category = $this->getDataGenerator()->create_category();
// Create some data we are going to use to update this category.
$data = new \stdClass();
$data->name = 'Category name change';
// Trigger and capture the event for updating a category.
$sink = $this->redirectEvents();
$category->update($data);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\course_category_updated', $event);
$this->assertEquals(\context_coursecat::instance($category->id), $event->get_context());
$url = new \moodle_url('/course/editcategory.php', array('id' => $event->objectid));
$this->assertEquals($url, $event->get_url());
// Create another category and a child category.
$category2 = $this->getDataGenerator()->create_category();
$childcat = $this->getDataGenerator()->create_category(array('parent' => $category2->id));
// Trigger and capture the event for changing the parent of a category.
$sink = $this->redirectEvents();
$childcat->change_parent($category);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\course_category_updated', $event);
$this->assertEquals(\context_coursecat::instance($childcat->id), $event->get_context());
// Trigger and capture the event for changing the sortorder of a category.
$sink = $this->redirectEvents();
$category2->change_sortorder_by_one(true);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\course_category_updated', $event);
$this->assertEquals(\context_coursecat::instance($category2->id), $event->get_context());
// Trigger and capture the event for deleting a category and moving it's children to another.
$sink = $this->redirectEvents();
$category->delete_move($category->id);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\course_category_updated', $event);
$this->assertEquals(\context_coursecat::instance($childcat->id), $event->get_context());
// Trigger and capture the event for hiding a category.
$sink = $this->redirectEvents();
$category2->hide();
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\course_category_updated', $event);
$this->assertEquals(\context_coursecat::instance($category2->id), $event->get_context());
// Trigger and capture the event for unhiding a category.
$sink = $this->redirectEvents();
$category2->show();
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\course_category_updated', $event);
$this->assertEquals(\context_coursecat::instance($category2->id), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* Test the email failed event.
*
* It's not possible to use the moodle API to simulate the failure of sending
* an email, so here we simply create the event and trigger it.
*/
public function test_email_failed(): void {
// Trigger event for failing to send email.
$event = \core\event\email_failed::create(array(
'context' => \context_system::instance(),
'userid' => 1,
'relateduserid' => 2,
'other' => array(
'subject' => 'This is a subject',
'message' => 'This is a message',
'errorinfo' => 'The email failed to send!'
)
));
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\email_failed', $event);
$this->assertEquals(\context_system::instance(), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* There is no api involved so the best we can do is test legacy data by triggering event manually.
*/
public function test_course_user_report_viewed(): void {
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$context = \context_course::instance($course->id);
$eventparams = array();
$eventparams['context'] = $context;
$eventparams['relateduserid'] = $user->id;
$eventparams['other'] = array();
$eventparams['other']['mode'] = 'grade';
$event = \core\event\course_user_report_viewed::create($eventparams);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\course_user_report_viewed', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* There is no api involved so the best we can do is test legacy data by triggering event manually.
*/
public function test_course_viewed(): void {
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$context = \context_course::instance($course->id);
// First try with no optional parameters.
$eventparams = array();
$eventparams['context'] = $context;
$event = \core\event\course_viewed::create($eventparams);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\course_viewed', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEventContextNotUsed($event);
// Now try with optional parameters.
$sectionnumber = 7;
$eventparams = array();
$eventparams['context'] = $context;
$eventparams['other'] = array('coursesectionnumber' => $sectionnumber);
$event = \core\event\course_viewed::create($eventparams);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$loggeddata = $event->get_data();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\course_viewed', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertEventContextNotUsed($event);
delete_course($course->id, false);
$restored = \core\event\base::restore($loggeddata, array('origin' => 'web', 'ip' => '127.0.0.1'));
$this->assertInstanceOf('\core\event\course_viewed', $restored);
$this->assertNull($restored->get_url());
}
public function test_recent_capability_viewed(): void {
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$context = \context_course::instance($course->id);
$event = \core\event\recent_activity_viewed::create(array('context' => $context));
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\recent_activity_viewed', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEventContextNotUsed($event);
$url = new \moodle_url('/course/recent.php', array('id' => $course->id));
$this->assertEquals($url, $event->get_url());
$event->get_name();
}
public function test_user_profile_viewed(): void {
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
// User profile viewed in course context.
$eventparams = array(
'objectid' => $user->id,
'relateduserid' => $user->id,
'courseid' => $course->id,
'context' => $coursecontext,
'other' => array(
'courseid' => $course->id,
'courseshortname' => $course->shortname,
'coursefullname' => $course->fullname
)
);
$event = \core\event\user_profile_viewed::create($eventparams);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\user_profile_viewed', $event);
$this->assertEventContextNotUsed($event);
// User profile viewed in user context.
$usercontext = \context_user::instance($user->id);
$eventparams['context'] = $usercontext;
unset($eventparams['courseid'], $eventparams['other']);
$event = \core\event\user_profile_viewed::create($eventparams);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\user_profile_viewed', $event);
$this->assertEventContextNotUsed($event);
}
/**
* There is no API associated with this event, so we will just test standard features.
*/
public function test_grade_viewed(): void {
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$event = \core_tests\event\grade_report_viewed::create(
array(
'context' => $coursecontext,
'courseid' => $course->id,
'userid' => $user->id,
)
);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\grade_report_viewed', $event);
$this->assertEquals($event->courseid, $course->id);
$this->assertEquals($event->userid, $user->id);
$this->assertEventContextNotUsed($event);
}
/**
* Test the database text field content replaced event.
*/
public function test_database_text_field_content_replaced(): void {
global $CFG;
require_once($CFG->dirroot . '/lib/adminlib.php');
// Trigger and capture the event for finding and replacing strings in the database.
$sink = $this->redirectEvents();
ob_start();
db_replace('searchstring', 'replacestring');
ob_end_clean();
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\core\event\database_text_field_content_replaced', $event);
$this->assertEquals(\context_system::instance(), $event->get_context());
$this->assertEquals('searchstring', $event->other['search']);
$this->assertEquals('replacestring', $event->other['replace']);
}
}
+79
View File
@@ -0,0 +1,79 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
/**
* Class core_event_grade_deleted_testcase
*
* Tests for event \core\event\grade_deleted
*
* @package core
* @category test
* @copyright 2014 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class grade_deleted_test extends \advanced_testcase {
/**
* Tests the event details.
*/
public function test_event(): void {
global $CFG;
require_once("$CFG->libdir/gradelib.php");
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$user = $this->getDataGenerator()->create_user();
$quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
// Create a grade item for the quiz.
$grade = array();
$grade['userid'] = $user->id;
$grade['rawgrade'] = 50;
grade_update('mod/quiz', $course->id, 'mod', 'quiz', $quiz->id, 0, $grade);
// Get the grade item and override it.
$gradeitem = \grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id,
'courseid' => $course->id));
$gradeitem->update_final_grade($user->id, 10, 'gradebook');
// Get the grade_grade object.
$gradegrade = new \grade_grade(array('userid' => $user->id, 'itemid' => $gradeitem->id), true);
$gradegrade->grade_item = $gradeitem;
// Trigger the event.
$sink = $this->redirectEvents();
course_delete_module($quiz->cmid);
$events = $sink->get_events();
$event = $events[1];
$sink->close();
// Check the event details are correct.
$grade = $event->get_grade();
$this->assertInstanceOf('grade_grade', $grade);
$this->assertInstanceOf('\core\event\grade_deleted', $event);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertSame($event->objecttable, 'grade_grades');
$this->assertEquals($event->objectid, $gradegrade->id);
$this->assertEquals($event->other['itemid'], $gradeitem->id);
$this->assertTrue($event->other['overridden']);
$this->assertEquals(10, $event->other['finalgrade']);
$this->assertEventContextNotUsed($event);
$this->assertEquals($gradegrade->id, $grade->id);
}
}
@@ -0,0 +1,76 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Grade item deleted event tests.
*
* @package core
* @category test
* @copyright 2020 Tom Dickman <tomdickman@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\event;
/**
* Test for grade item deleted event.
*
* @package core
* @category test
* @copyright 2020 Tom Dickman <tomdickman@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\event\grade_item_deleted
*/
class grade_item_deleted_test extends \advanced_testcase {
/**
* Test the grade item deleted event.
*
* @covers ::create_from_grade_item
*/
public function test_grade_item_deleted(): void {
global $DB;
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$gradeitemrecord = $this->getDataGenerator()->create_grade_item(['courseid' => $course->id]);
$gradeitem = \grade_item::fetch(['id' => $gradeitemrecord->id, 'courseid' => $course->id]);
$countgradeitems = $DB->count_records('grade_items');
// Trigger and capture the event for deleting a grade item.
$sink = $this->redirectEvents();
$gradeitem->delete();
$events = $sink->get_events();
$sink->close();
// Event should only be triggered once.
$this->assertCount(1, $events);
$event = reset($events);
// Expect that the grade item was deleted and the event data is valid.
$this->assertEquals($countgradeitems - 1, $DB->count_records('grade_items'));
$this->assertInstanceOf('\core\event\grade_item_deleted', $event);
$eventdata = $event->get_data();
$this->assertEquals($gradeitem->id, $eventdata['objectid']);
$this->assertEquals($gradeitem->courseid, $eventdata['courseid']);
$this->assertEquals(\context_course::instance($gradeitem->courseid)->id, $eventdata['contextid']);
$this->assertEquals($gradeitem->itemname, $eventdata['other']['itemname']);
$this->assertEquals($gradeitem->itemtype, $eventdata['other']['itemtype']);
$this->assertEquals($gradeitem->itemmodule, $eventdata['other']['itemmodule']);
}
}
+319
View File
@@ -0,0 +1,319 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
use profile_define_base;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/user/profile/definelib.php');
/**
* Tests the events related to the user profile fields and categories.
*
* @package core
* @category test
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class profile_field_test extends \advanced_testcase {
/**
* Test set up.
*/
public function setUp(): void {
$this->resetAfterTest();
}
/**
* Test that triggering the user_info_category_created event works as expected.
*/
public function test_user_info_category_created_event(): void {
// Create a new profile category.
$cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Trigger the event.
$sink = $this->redirectEvents();
\core\event\user_info_category_created::create_from_category($cat1)->trigger();
$events = $sink->get_events();
$sink->close();
// Confirm we got the right number of events.
$this->assertCount(1, $events);
// Validate that the event was correctly triggered.
$event = reset($events);
$this->assertInstanceOf('\core\event\user_info_category_created', $event);
$this->assertEquals($event->objectid, $cat1->id);
$this->assertEquals($event->other['name'], $cat1->name);
}
/**
* Test that moving a user info category triggers an updated event.
*/
public function test_user_info_category_updated_event(): void {
global $DB;
// Create new profile categories.
$cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
$cat2 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category 2']);
// Trigger the events.
$sink = $this->redirectEvents();
profile_move_category($cat1->id, 'down');
$events = $sink->get_events();
$sink->close();
// Should now have two events.
$this->assertCount(2, $events);
$event1 = array_shift($events);
$event2 = array_shift($events);
// Validate that the events were correctly triggered.
$this->assertInstanceOf('\core\event\user_info_category_updated', $event1);
$this->assertEquals($event1->objectid, $cat1->id);
$this->assertEquals($event1->other['name'], $cat1->name);
$this->assertInstanceOf('\core\event\user_info_category_updated', $event2);
$this->assertEquals($event2->objectid, $cat2->id);
$this->assertEquals($event2->other['name'], $cat2->name);
}
/**
* Test that deleting a user info category triggers a delete event.
*/
public function test_user_info_category_deleted_event(): void {
// Create new profile categories.
$cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
$cat2 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category 2']);
// Trigger the event.
$sink = $this->redirectEvents();
profile_delete_category($cat2->id);
$events = $sink->get_events();
$sink->close();
// Confirm we got the right number of events.
$this->assertCount(1, $events);
// Validate that the event was correctly triggered.
$event = reset($events);
$this->assertInstanceOf('\core\event\user_info_category_deleted', $event);
$this->assertEquals($event->objectid, $cat2->id);
$this->assertEquals($event->other['name'], $cat2->name);
}
/**
* Test that creating a user info field triggers a create event.
*/
public function test_user_info_field_created_event(): void {
global $DB;
// Create a new profile category.
$cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
$data = new \stdClass();
$data->datatype = 'text';
$data->shortname = 'example';
$data->name = 'Example field';
$data->description = 'Hello this is an example.';
$data->required = false;
$data->locked = false;
$data->forceunique = false;
$data->signup = false;
$data->visible = '0';
$data->categoryid = $cat1->id;
// Trigger the event.
$sink = $this->redirectEvents();
$field = new profile_define_base();
$field->define_save($data);
$events = $sink->get_events();
$sink->close();
// Get the field that was created.
$field = $DB->get_record('user_info_field', array('shortname' => $data->shortname));
// Confirm we got the right number of events.
$this->assertCount(1, $events);
// Validate that the event was correctly triggered.
$event = reset($events);
$this->assertInstanceOf('\core\event\user_info_field_created', $event);
$this->assertEquals($event->objectid, $field->id);
$this->assertEquals($event->other['shortname'], $field->shortname);
$this->assertEquals($event->other['name'], $field->name);
$this->assertEquals($event->other['datatype'], $field->datatype);
}
/**
* Test that updating a user info field triggers an update event.
*/
public function test_user_info_field_updated_event(): void {
// Create a new profile category.
$cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
$data = $this->getDataGenerator()->create_custom_profile_field([
'datatype' => 'text',
'shortname' => 'example',
'name' => 'Example field',
'description' => 'Hello this is an example.',
'categoryid' => $cat1->id,
]);
// Trigger the event.
$sink = $this->redirectEvents();
$field = new profile_define_base();
$field->define_save($data);
$events = $sink->get_events();
$sink->close();
// Confirm we got the right number of events.
$this->assertCount(1, $events);
// Validate that the event was correctly triggered.
$event = reset($events);
$this->assertInstanceOf('\core\event\user_info_field_updated', $event);
$this->assertEquals($event->objectid, $data->id);
$this->assertEquals($event->other['shortname'], $data->shortname);
$this->assertEquals($event->other['name'], $data->name);
$this->assertEquals($event->other['datatype'], $data->datatype);
}
/**
* Test that moving a field triggers update events.
*/
public function test_user_info_field_updated_event_move_field(): void {
// Create a new profile category.
$cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
$field1 = $this->getDataGenerator()->create_custom_profile_field([
'datatype' => 'text',
'shortname' => 'example',
'name' => 'Example field',
'description' => 'Hello this is an example.',
'categoryid' => $cat1->id,
]);
// Create another that we will be moving.
$field2 = $this->getDataGenerator()->create_custom_profile_field([
'datatype' => 'text',
'shortname' => 'example2',
'name' => 'Example field 2',
'categoryid' => $cat1->id,
]);
// Trigger the events.
$sink = $this->redirectEvents();
profile_move_field($field2->id, 'up');
$events = $sink->get_events();
$sink->close();
// Should now have two events.
$this->assertCount(2, $events);
$event1 = array_shift($events);
$event2 = array_shift($events);
// Validate that the events were correctly triggered.
$this->assertInstanceOf('\core\event\user_info_field_updated', $event1);
$this->assertEquals($event1->objectid, $field2->id);
$this->assertEquals($event1->other['shortname'], $field2->shortname);
$this->assertEquals($event1->other['name'], $field2->name);
$this->assertEquals($event1->other['datatype'], $field2->datatype);
$this->assertInstanceOf('\core\event\user_info_field_updated', $event2);
$this->assertEquals($event2->objectid, $field1->id);
$this->assertEquals($event2->other['shortname'], $field1->shortname);
$this->assertEquals($event2->other['name'], $field1->name);
$this->assertEquals($event2->other['datatype'], $field1->datatype);
}
/**
* Test that when we delete a category that contains a field, that the field being moved to
* another category triggers an update event.
*/
public function test_user_info_field_updated_event_delete_category(): void {
// Create profile categories.
$cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
$cat2 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
$field = $this->getDataGenerator()->create_custom_profile_field([
'datatype' => 'text',
'shortname' => 'example',
'name' => 'Example field',
'description' => 'Hello this is an example.',
'categoryid' => $cat1->id,
]);
// Trigger the event.
$sink = $this->redirectEvents();
profile_delete_category($cat1->id);
$events = $sink->get_events();
$sink->close();
// Check we got the right number of events.
$this->assertCount(2, $events);
// Validate that the event was correctly triggered.
$event = reset($events);
$this->assertInstanceOf('\core\event\user_info_field_updated', $event);
$this->assertEquals($event->objectid, $field->id);
$this->assertEquals($event->other['shortname'], $field->shortname);
$this->assertEquals($event->other['name'], $field->name);
$this->assertEquals($event->other['datatype'], $field->datatype);
}
/**
* Test that deleting a user info field triggers a delete event.
*/
public function test_user_info_field_deleted_event(): void {
// Create a new profile category.
$cat1 = $this->getDataGenerator()->create_custom_profile_field_category(['name' => 'Example category']);
// Create a new profile field.
$data = $this->getDataGenerator()->create_custom_profile_field([
'datatype' => 'text',
'shortname' => 'delete',
'name' => 'Example field for delete',
'description' => 'Hello this is an example.',
'categoryid' => $cat1->id,
]);
// Trigger the event.
$sink = $this->redirectEvents();
profile_delete_field($data->id);
$events = $sink->get_events();
$sink->close();
// Confirm we got the right number of events.
$this->assertCount(1, $events);
// Validate that the event was correctly triggered.
$event = reset($events);
$this->assertInstanceOf('\core\event\user_info_field_deleted', $event);
$this->assertEquals($event->objectid, $data->id);
$this->assertEquals($event->other['shortname'], $data->shortname);
$this->assertEquals($event->other['name'], $data->name);
$this->assertEquals($event->other['datatype'], $data->datatype);
}
}
+54
View File
@@ -0,0 +1,54 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/../fixtures/event_fixtures.php');
/**
* Tests for event manager, base event and observers.
*
* @package core
* @category phpunit
* @copyright 2014 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class unknown_logged_test extends \advanced_testcase {
public function test_restore_event(): void {
$event1 = \core_tests\event\unittest_executed::create(array('context' => \context_system::instance(), 'other' => array('sample' => 1, 'xx' => 10)));
$data1 = $event1->get_data();
$data1['eventname'] = '\mod_xx\event\xx_yy';
$data1['component'] = 'mod_xx';
$data1['action'] = 'yy';
$data1['target'] = 'xx';
$extra1 = array('origin' => 'cli');
$event2 = \core\event\base::restore($data1, $extra1);
$data2 = $event2->get_data();
$extra2 = $event2->get_logextra();
$this->assertInstanceOf('core\event\unknown_logged', $event2);
$this->assertTrue($event2->is_triggered());
$this->assertTrue($event2->is_restored());
$this->assertNull($event2->get_url());
$this->assertEquals($data1, $data2);
$this->assertEquals($extra1, $extra2);
}
}
+225
View File
@@ -0,0 +1,225 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/mathslib.php');
/**
* Tests for event \core\event\user_graded
*
* @package core
* @category test
* @copyright 2014 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class user_graded_test extends \advanced_testcase {
/**
* Tests set up.
*/
public function setUp(): void {
$this->resetAfterTest();
}
/**
* Tests the event details.
*/
public function test_event(): void {
global $CFG;
require_once("$CFG->libdir/gradelib.php");
$course = $this->getDataGenerator()->create_course();
$user = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user->id, $course->id);
$grade_category = \grade_category::fetch_course_category($course->id);
$grade_category->load_grade_item();
$grade_item = $grade_category->grade_item;
$grade_item->update_final_grade($user->id, 10, 'gradebook');
$grade_grade = new \grade_grade(array('userid' => $user->id, 'itemid' => $grade_item->id), true);
$grade_grade->grade_item = $grade_item;
$event = \core\event\user_graded::create_from_grade($grade_grade);
$this->assertEquals(\context_course::instance($course->id), $event->get_context());
$this->assertSame($event->objecttable, 'grade_grades');
$this->assertEquals($event->objectid, $grade_grade->id);
$this->assertEquals($event->other['itemid'], $grade_item->id);
$this->assertTrue($event->other['overridden']);
$this->assertEquals(10, $event->other['finalgrade']);
// Trigger the events.
$sink = $this->redirectEvents();
$event->trigger();
$result = $sink->get_events();
$sink->close();
$this->assertCount(1, $result);
$event = reset($result);
$this->assertEventContextNotUsed($event);
$grade = $event->get_grade();
$this->assertInstanceOf('grade_grade', $grade);
$this->assertEquals($grade_grade->id, $grade->id);
}
/**
* Tests that the event is fired in the correct locations in core.
*/
public function test_event_is_triggered(): void {
global $DB;
// Create the items we need to test with.
$course = $this->getDataGenerator()->create_course();
$user = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user->id, $course->id);
$quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
$quizitemparams = array('itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id,
'courseid' => $course->id);
$gradeitem = \grade_item::fetch($quizitemparams);
$courseitem = \grade_item::fetch_course_item($course->id);
// Now mark the quiz using grade_update as this is the function that modules use.
$grade = array();
$grade['userid'] = $user->id;
$grade['rawgrade'] = 60;
$sink = $this->redirectEvents();
grade_update('mod/quiz', $course->id, 'mod', 'quiz', $quiz->id, 0, $grade);
$events = $sink->get_events();
$sink->close();
// Ensure we have two user_graded events, one for the item, one for the course.
$this->assertEquals(2, count($events));
$this->assertInstanceOf('\core\event\user_graded', $events[0]);
$this->assertEquals($gradeitem->id, $events[0]->other['itemid']);
$this->assertInstanceOf('\core\event\user_graded', $events[1]);
$this->assertEquals($courseitem->id, $events[1]->other['itemid']);
// Remove the grades, force the regrading and re-fetch the item. This is needed because the item
// will be set as needing an update when the grades are deleted.
$gradeitem->delete_all_grades();
grade_regrade_final_grades($course->id);
$gradeitem = \grade_item::fetch($quizitemparams);
// Now, create a grade using \grade_item::update_final_grade().
$sink = $this->redirectEvents();
$gradeitem->update_raw_grade($user->id, 10);
$events = $sink->get_events();
$sink->close();
// Ensure we have two user_graded events, one for the item, one for the course.
$this->assertEquals(2, count($events));
$this->assertInstanceOf('\core\event\user_graded', $events[0]);
$this->assertEquals($gradeitem->id, $events[0]->other['itemid']);
$this->assertInstanceOf('\core\event\user_graded', $events[1]);
$this->assertEquals($courseitem->id, $events[1]->other['itemid']);
// Now, update this grade using \grade_item::update_raw_grade().
$sink = $this->redirectEvents();
$gradeitem->update_raw_grade($user->id, 20);
$events = $sink->get_events();
$sink->close();
// Ensure we have two user_graded events, one for the item, one for the course.
$this->assertEquals(2, count($events));
$this->assertInstanceOf('\core\event\user_graded', $events[0]);
$this->assertEquals($gradeitem->id, $events[0]->other['itemid']);
$this->assertInstanceOf('\core\event\user_graded', $events[1]);
$this->assertEquals($courseitem->id, $events[1]->other['itemid']);
// Remove the grades, force the regrading and re-fetch the item. This is needed because the item
// will be set as needing an update when the grades are deleted.
$gradeitem->delete_all_grades();
grade_regrade_final_grades($course->id);
$gradeitem = \grade_item::fetch($quizitemparams);
// Now, create a grade using \grade_item::update_final_grade().
$sink = $this->redirectEvents();
$gradeitem->update_final_grade($user->id, 30);
$events = $sink->get_events();
$sink->close();
// Ensure we have two user_graded events, one for the item, one for the course.
$this->assertEquals(2, count($events));
$this->assertInstanceOf('\core\event\user_graded', $events[0]);
$this->assertEquals($gradeitem->id, $events[0]->other['itemid']);
$this->assertInstanceOf('\core\event\user_graded', $events[1]);
$this->assertEquals($courseitem->id, $events[1]->other['itemid']);
// Now, update this grade using \grade_item::update_final_grade().
$sink = $this->redirectEvents();
$gradeitem->update_final_grade($user->id, 40);
$events = $sink->get_events();
$sink->close();
// Ensure we have two user_graded events, one for the item, one for the course.
$this->assertEquals(2, count($events));
$this->assertInstanceOf('\core\event\user_graded', $events[0]);
$this->assertEquals($gradeitem->id, $events[0]->other['itemid']);
$this->assertInstanceOf('\core\event\user_graded', $events[1]);
$this->assertEquals($courseitem->id, $events[1]->other['itemid']);
// Remove the overridden flag from the grade, this was set by \grade_item::update_final_grade().
$gradegrade = \grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user->id));
$gradegrade->set_overridden(false, false);
// Let's change the calculation to anything that won't cause an error.
$calculation = \calc_formula::unlocalize("=3");
$gradeitem->set_calculation($calculation);
// Now force the computation of the grade.
$sink = $this->redirectEvents();
grade_regrade_final_grades($course->id);
$events = $sink->get_events();
$sink->close();
// Ensure we have two user_graded events, one for the item, one for the course.
$this->assertEquals(2, count($events));
$this->assertInstanceOf('\core\event\user_graded', $events[0]);
$this->assertEquals($gradeitem->id, $events[0]->other['itemid']);
$this->assertInstanceOf('\core\event\user_graded', $events[1]);
$this->assertEquals($courseitem->id, $events[1]->other['itemid']);
// Now, let's trick the gradebook, we manually update a grade, and flag the grade item as
// needing a regrading, so we can trigger the event in \grade_item::regrade_final_grades().
$gradeitem = \grade_item::fetch($quizitemparams);
$gradeitem->set_calculation('');
$gradegrade = \grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user->id));
$gradegrade->rawgrade = 50;
$gradegrade->update();
$sink = $this->redirectEvents();
grade_regrade_final_grades($course->id);
$events = $sink->get_events();
$sink->close();
// Ensure we have two user_graded events, one for the item, one for the course.
$this->assertEquals(2, count($events));
$this->assertInstanceOf('\core\event\user_graded', $events[0]);
$this->assertEquals($gradeitem->id, $events[0]->other['itemid']);
$this->assertInstanceOf('\core\event\user_graded', $events[1]);
$this->assertEquals($courseitem->id, $events[1]->other['itemid']);
}
}
@@ -0,0 +1,65 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\event;
/**
* Tests for event \core\event\user_password_updated
*
* @package core
* @category test
* @copyright 2014 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class user_password_updated_test extends \advanced_testcase {
/**
* Test the event.
*/
public function test_event(): void {
$this->resetAfterTest();
$user1 = $this->getDataGenerator()->create_user();
$context1 = \context_user::instance($user1->id);
$user2 = $this->getDataGenerator()->create_user();
$context2 = \context_user::instance($user2->id);
$this->setUser($user1);
// Changing own password.
$event = \core\event\user_password_updated::create_from_user($user1);
$this->assertEventContextNotUsed($event);
$this->assertEquals($user1->id, $event->relateduserid);
$this->assertSame($context1, $event->get_context());
$this->assertFalse($event->other['forgottenreset']);
$event->trigger();
// Changing password of other user.
$event = \core\event\user_password_updated::create_from_user($user2);
$this->assertEventContextNotUsed($event);
$this->assertEquals($user2->id, $event->relateduserid);
$this->assertSame($context2, $event->get_context());
$this->assertFalse($event->other['forgottenreset']);
$event->trigger();
// Password reset.
$event = \core\event\user_password_updated::create_from_user($user1, true);
$this->assertEventContextNotUsed($event);
$this->assertEquals($user1->id, $event->relateduserid);
$this->assertSame($context1, $event->get_context());
$this->assertTrue($event->other['forgottenreset']);
$event->trigger();
}
}