MDL-62660 tool_dataprivacy: Add and update PHPUnit tests
[moodle.git] / admin / tool / monitor / tests / eventobservers_test.php
bloba1cb38423da4e3ef3bd6563a121cb371636e8655
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * Unit tests for event observers.
20 * @package tool_monitor
21 * @category test
22 * @copyright 2014 onwards Ankit Agarwal <ankit.agrr@gmail.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
29 require_once($CFG->dirroot . '/blog/locallib.php');
30 require_once($CFG->dirroot . '/blog/lib.php');
32 /**
33 * Class tool_monitor_eventobservers_testcase
35 * Tests for event observers
37 class tool_monitor_eventobservers_testcase extends advanced_testcase {
38 /**
39 * Set up method.
41 public function setUp() {
42 // Enable monitor.
43 set_config('enablemonitor', 1, 'tool_monitor');
46 /**
47 * Test observer for course delete event.
49 public function test_course_deleted() {
50 global $DB;
52 $this->setAdminUser();
53 $this->resetAfterTest(true);
55 $user = $this->getDataGenerator()->create_user();
56 $course1 = $this->getDataGenerator()->create_course();
57 $course2 = $this->getDataGenerator()->create_course();
58 $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
60 $rule = new stdClass();
61 $rule->userid = $user->id;
62 $rule->courseid = $course1->id;
63 $rule->plugin = 'test';
65 $sub = new stdClass();
66 $sub->courseid = $course1->id;
67 $sub->userid = $user->id;
69 // Add 10 rules for this course with subscriptions.
70 for ($i = 0; $i < 10; $i++) {
71 $createdrule = $monitorgenerator->create_rule($rule);
72 $sub->ruleid = $createdrule->id;
73 $monitorgenerator->create_subscription($sub);
76 // Add 10 random rules for course 2.
77 $rule->courseid = $course2->id;
78 for ($i = 0; $i < 10; $i++) {
79 $createdrule = $monitorgenerator->create_rule($rule);
80 $sub->courseid = $rule->courseid;
81 $sub->ruleid = $createdrule->id;
82 $monitorgenerator->create_subscription($sub);
85 // Add a site rule.
86 $rule = new stdClass();
87 $rule->userid = $user->id;
88 $rule->courseid = 0;
89 $rule->plugin = 'core';
90 $monitorgenerator->create_rule($rule);
92 // Verify that if we do not specify that we do not want the site rules, they are returned.
93 $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id);
94 $this->assertCount(11, $courserules);
96 // Verify data before course delete.
97 $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
98 $this->assertCount(20, $totalrules);
99 $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id, 0, 0, false);
100 $this->assertCount(10, $courserules);
101 $this->assertEquals(20, $DB->count_records('tool_monitor_subscriptions'));
102 $coursesubs = \tool_monitor\subscription_manager::get_user_subscriptions_for_course($course1->id, 0, 0, $user->id);
103 $this->assertCount(10, $coursesubs);
105 // Let us delete the course now.
106 delete_course($course1->id, false);
108 // Confirm the site rule still exists.
109 $this->assertEquals(1, $DB->count_records('tool_monitor_rules', array('courseid' => 0)));
111 // Verify data after course delete.
112 $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
113 $this->assertCount(10, $totalrules);
114 $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id, 0, 0, false);
115 $this->assertCount(0, $courserules); // Making sure all rules are deleted.
116 $this->assertEquals(10, $DB->count_records('tool_monitor_subscriptions'));
117 $coursesubs = \tool_monitor\subscription_manager::get_user_subscriptions_for_course($course1->id, 0, 0, $user->id);
118 $this->assertCount(0, $coursesubs); // Making sure all subscriptions are deleted.
122 * This tests if writing of the events to the table tool_monitor_events is working fine.
124 public function test_flush() {
125 global $DB;
127 $this->resetAfterTest();
129 // Create the necessary items for testing.
130 $user = $this->getDataGenerator()->create_user();
131 $course = $this->getDataGenerator()->create_course();
132 $course2 = $this->getDataGenerator()->create_course();
133 $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
135 // Fire a bunch of events.
136 // Trigger a bunch of other events.
137 $eventparams = array(
138 'context' => context_course::instance($course->id)
140 for ($i = 0; $i < 5; $i++) {
141 \core\event\course_viewed::create($eventparams)->trigger();
142 \mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
143 \mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
146 // Confirm that nothing was stored in the tool_monitor_events table
147 // as we do not have any subscriptions associated for the above events.
148 $this->assertEquals(0, $DB->count_records('tool_monitor_events'));
150 // Now, let's create a rule so an event can be stored.
151 $rule = new stdClass();
152 $rule->courseid = $course->id;
153 $rule->plugin = 'mod_book';
154 $rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
155 $rule = $monitorgenerator->create_rule($rule);
157 // Let's subscribe to this rule.
158 $sub = new stdClass;
159 $sub->courseid = $course->id;
160 $sub->ruleid = $rule->id;
161 $sub->userid = $user->id;
162 $monitorgenerator->create_subscription($sub);
164 // Again, let's just fire more events to make sure they still aren't stored.
165 for ($i = 0; $i < 5; $i++) {
166 \core\event\course_viewed::create($eventparams)->trigger();
167 \mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
168 \mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
171 // Fire the event we want to capture.
172 $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
173 $event->trigger();
175 // Check that the event data is valid.
176 $events = $DB->get_records('tool_monitor_events');
177 $this->assertEquals(1, count($events));
178 $monitorevent = array_pop($events);
179 $this->assertEquals($event->eventname, $monitorevent->eventname);
180 $this->assertEquals($event->contextid, $monitorevent->contextid);
181 $this->assertEquals($event->contextlevel, $monitorevent->contextlevel);
182 $this->assertEquals($event->get_url()->out(), $monitorevent->link);
183 $this->assertEquals($event->courseid, $monitorevent->courseid);
184 $this->assertEquals($event->timecreated, $monitorevent->timecreated);
186 // Remove the stored events.
187 $DB->delete_records('tool_monitor_events');
189 // Now, let's create a site wide rule.
190 $rule = new stdClass();
191 $rule->courseid = 0;
192 $rule->plugin = 'mod_book';
193 $rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
194 $rule = $monitorgenerator->create_rule($rule);
196 // Let's subscribe to this rule.
197 $sub = new stdClass;
198 $sub->courseid = 0;
199 $sub->ruleid = $rule->id;
200 $sub->userid = $user->id;
201 $monitorgenerator->create_subscription($sub);
203 // Fire the event we want to capture - but in a different course.
204 $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course2);
205 $event->trigger();
207 // Check that the event data is valid.
208 $events = $DB->get_records('tool_monitor_events');
209 $this->assertEquals(1, count($events));
210 $monitorevent = array_pop($events);
211 $this->assertEquals($event->eventname, $monitorevent->eventname);
212 $this->assertEquals($event->contextid, $monitorevent->contextid);
213 $this->assertEquals($event->contextlevel, $monitorevent->contextlevel);
214 $this->assertEquals($event->get_url()->out(), $monitorevent->link);
215 $this->assertEquals($event->courseid, $monitorevent->courseid);
216 $this->assertEquals($event->timecreated, $monitorevent->timecreated);
220 * Test the notification sending features.
222 public function test_process_event() {
224 global $DB, $USER;
226 $this->resetAfterTest();
227 $this->setAdminUser();
228 $msgsink = $this->redirectMessages();
230 // Generate data.
231 $course = $this->getDataGenerator()->create_course();
232 $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
234 $rulerecord = new stdClass();
235 $rulerecord->courseid = $course->id;
236 $rulerecord->eventname = '\mod_book\event\course_module_instance_list_viewed';
237 $rulerecord->frequency = 1;
239 $rule = $toolgenerator->create_rule($rulerecord);
241 $subrecord = new stdClass();
242 $subrecord->courseid = $course->id;
243 $subrecord->ruleid = $rule->id;
244 $subrecord->userid = $USER->id;
245 $toolgenerator->create_subscription($subrecord);
247 $recordexists = $DB->record_exists('task_adhoc', array('component' => 'tool_monitor'));
248 $this->assertFalse($recordexists);
250 // Now let us trigger the event.
251 $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
252 $event->trigger();
254 $this->verify_processed_data($msgsink);
256 // Clean up.
257 \tool_monitor\rule_manager::delete_rule($rule->id);
258 $DB->delete_records('tool_monitor_events');
260 // Let us create a rule with more than 1 frequency.
261 $rulerecord->frequency = 5;
262 $rule = $toolgenerator->create_rule($rulerecord);
263 $subrecord->ruleid = $rule->id;
264 $toolgenerator->create_subscription($subrecord);
266 // Let us trigger events.
267 for ($i = 0; $i < 5; $i++) {
268 $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
269 $event->trigger();
270 if ($i != 4) {
271 $this->verify_message_not_sent_yet($msgsink);
275 $this->verify_processed_data($msgsink);
277 // Clean up.
278 \tool_monitor\rule_manager::delete_rule($rule->id);
279 $DB->delete_records('tool_monitor_events');
281 // Now let us create a rule specific to a module instance.
282 $cm = new stdClass();
283 $cm->course = $course->id;
284 $book = $this->getDataGenerator()->create_module('book', $cm);
285 $rulerecord->eventname = '\mod_book\event\course_module_viewed';
286 $rulerecord->cmid = $book->cmid;
287 $rule = $toolgenerator->create_rule($rulerecord);
288 $subrecord->ruleid = $rule->id;
289 $toolgenerator->create_subscription($subrecord);
291 // Let us trigger events.
292 $params = array(
293 'context' => context_module::instance($book->cmid),
294 'objectid' => $book->id
296 for ($i = 0; $i < 5; $i++) {
297 $event = \mod_book\event\course_module_viewed::create($params);
298 $event->trigger();
299 if ($i != 4) {
300 $this->verify_message_not_sent_yet($msgsink);
304 $this->verify_processed_data($msgsink);
306 // Clean up.
307 \tool_monitor\rule_manager::delete_rule($rule->id);
308 $DB->delete_records('tool_monitor_events');
310 // Now let us create a rule for event that happens in category context events.
311 $rulerecord->eventname = '\core\event\course_category_created';
312 $rulerecord->courseid = 0;
313 $rule = $toolgenerator->create_rule($rulerecord);
314 $subrecord->courseid = 0;
315 $subrecord->ruleid = $rule->id;
316 $toolgenerator->create_subscription($subrecord);
318 // Let us trigger events.
319 for ($i = 0; $i < 5; $i++) {
320 $this->getDataGenerator()->create_category();
321 if ($i != 4) {
322 $this->verify_message_not_sent_yet($msgsink);
325 $this->verify_processed_data($msgsink);
327 // Clean up.
328 \tool_monitor\rule_manager::delete_rule($rule->id);
329 $DB->delete_records('tool_monitor_events');
331 // Now let us create a rule at site level.
332 $rulerecord->eventname = '\core\event\blog_entry_created';
333 $rulerecord->courseid = 0;
334 $rule = $toolgenerator->create_rule($rulerecord);
335 $subrecord->courseid = 0;
336 $subrecord->ruleid = $rule->id;
337 $toolgenerator->create_subscription($subrecord);
339 // Let us trigger events.
340 $blog = new blog_entry();
341 $blog->subject = "Subject of blog";
342 $blog->userid = $USER->id;
343 $states = blog_entry::get_applicable_publish_states();
344 $blog->publishstate = reset($states);
345 for ($i = 0; $i < 5; $i++) {
346 $newblog = fullclone($blog);
347 $newblog->add();
348 if ($i != 4) {
349 $this->verify_message_not_sent_yet($msgsink);
353 $this->verify_processed_data($msgsink);
357 * Test that same events are not used twice to calculate conditions for a single subscription.
359 public function test_multiple_notification_not_sent() {
360 global $USER;
362 $this->resetAfterTest();
363 $this->setAdminUser();
364 $messagesink = $this->redirectMessages();
366 // Generate data.
367 $course = $this->getDataGenerator()->create_course();
368 $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
370 $rulerecord = new stdClass();
371 $rulerecord->courseid = $course->id;
372 $rulerecord->eventname = '\mod_book\event\course_module_instance_list_viewed';
373 $rulerecord->frequency = 5;
375 $rule = $toolgenerator->create_rule($rulerecord);
377 $subrecord = new stdClass();
378 $subrecord->courseid = $course->id;
379 $subrecord->ruleid = $rule->id;
380 $subrecord->userid = $USER->id;
381 $toolgenerator->create_subscription($subrecord);
383 for ($i = 0; $i < 7; $i++) {
384 // Now let us trigger 7 instances of the event.
385 $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
386 $event->trigger();
387 $this->waitForSecond(); // Add a second delay, to prevent time collisions.
389 $this->run_adhock_tasks();
390 $messages = $messagesink->get_messages();
391 $this->assertCount(1, $messages); // There should be only one message not 3.
392 for ($i = 0; $i < 3; $i++) {
393 // Now let us trigger 5 more instances of the event.
394 $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
395 $event->trigger();
398 $this->run_adhock_tasks();
399 $messages = $messagesink->get_messages();
400 $this->assertCount(2, $messages); // There should be two messages now.
404 * Run adhoc tasks.
406 protected function run_adhock_tasks() {
407 while ($task = \core\task\manager::get_next_adhoc_task(time())) {
408 $task->execute();
409 \core\task\manager::adhoc_task_complete($task);
411 $this->expectOutputRegex("/^Sending message to the user with id \d+ for the subscription with id \d+\.\.\..Sent./ms");
415 * Verify that task was scheduled and a message was sent as expected.
417 * @param phpunit_message_sink $msgsink Message sink
419 protected function verify_processed_data(phpunit_message_sink $msgsink) {
420 global $DB, $USER;
422 $recordexists = $DB->count_records('task_adhoc', array('component' => 'tool_monitor'));
423 $this->assertEquals(1, $recordexists); // We should have an adhock task now to send notifications.
424 $this->run_adhock_tasks();
425 $this->assertEquals(1, $msgsink->count());
426 $msgs = $msgsink->get_messages();
427 $msg = array_pop($msgs);
428 $this->assertEquals($USER->id, $msg->useridto);
429 $this->assertEquals(1, $msg->notification);
430 $msgsink->clear();
434 * Verify that a message was not sent.
436 * @param phpunit_message_sink $msgsink Message sink
438 protected function verify_message_not_sent_yet(phpunit_message_sink $msgsink) {
439 $msgs = $msgsink->get_messages();
440 $this->assertCount(0, $msgs);
441 $msgsink->clear();
445 * Tests for replace_placeholders method.
447 public function test_replace_placeholders() {
448 global $USER;
450 $this->resetAfterTest();
451 $this->setAdminUser();
452 $msgsink = $this->redirectMessages();
454 // Generate data.
455 $course = $this->getDataGenerator()->create_course();
456 $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
457 $context = \context_user::instance($USER->id, IGNORE_MISSING);
459 // Creating book.
460 $cm = new stdClass();
461 $cm->course = $course->id;
462 $book = $this->getDataGenerator()->create_module('book', $cm);
464 // Creating rule.
465 $rulerecord = new stdClass();
466 $rulerecord->courseid = $course->id;
467 $rulerecord->eventname = '\mod_book\event\course_module_viewed';
468 $rulerecord->cmid = $book->cmid;
469 $rulerecord->frequency = 1;
470 $rulerecord->template = '## {link} ##
472 * {modulelink}
473 * __{rulename}__
474 * {description}
475 * {eventname}';
476 $rulerecord->templateformat = FORMAT_MARKDOWN;
478 $rule = $toolgenerator->create_rule($rulerecord);
480 // Creating subscription.
481 $subrecord = new stdClass();
482 $subrecord->courseid = $course->id;
483 $subrecord->ruleid = $rule->id;
484 $subrecord->userid = $USER->id;
485 $toolgenerator->create_subscription($subrecord);
487 // Now let us trigger the event.
488 $params = array(
489 'context' => context_module::instance($book->cmid),
490 'objectid' => $book->id
493 $event = \mod_book\event\course_module_viewed::create($params);
494 $event->trigger();
495 $this->run_adhock_tasks();
496 $msgs = $msgsink->get_messages();
497 $msg = array_pop($msgs);
499 $modurl = new moodle_url('/mod/book/view.php', array('id' => $book->cmid));
501 $this->assertContains('<h2>'.$event->get_url()->out().'</h2>', $msg->fullmessagehtml);
502 $this->assertContains('<li>'.$modurl->out().'</li>', $msg->fullmessagehtml);
503 $this->assertContains('<li><strong>'.$rule->get_name($context).'</strong></li>', $msg->fullmessagehtml);
504 $this->assertContains('<li>'.$rule->get_description($context).'</li>', $msg->fullmessagehtml);
505 $this->assertContains('<li>'.$rule->get_event_name().'</li>', $msg->fullmessagehtml);
507 $this->assertEquals(FORMAT_PLAIN, $msg->fullmessageformat);
508 $this->assertNotContains('<h2>', $msg->fullmessage);
509 $this->assertNotContains('##', $msg->fullmessage);
510 $this->assertContains(strtoupper($event->get_url()->out()), $msg->fullmessage);
511 $this->assertContains('* '.$modurl->out(), $msg->fullmessage);
512 $this->assertContains('* '.strtoupper($rule->get_name($context)), $msg->fullmessage);
513 $this->assertContains('* '.$rule->get_description($context), $msg->fullmessage);
514 $this->assertContains('* '.$rule->get_event_name(), $msg->fullmessage);
518 * Test observer for user delete event.
520 public function test_user_deleted() {
521 global $DB;
523 $this->setAdminUser();
524 $this->resetAfterTest(true);
526 $user = $this->getDataGenerator()->create_user();
527 $course1 = $this->getDataGenerator()->create_course();
528 $course2 = $this->getDataGenerator()->create_course();
529 $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
531 $rule = new stdClass();
532 $rule->userid = $user->id;
533 $rule->courseid = $course1->id;
534 $rule->plugin = 'test';
536 $sub = new stdClass();
537 $sub->courseid = $course1->id;
538 $sub->userid = $user->id;
540 // Add 10 rules for this course with subscriptions.
541 for ($i = 0; $i < 10; $i++) {
542 $createdrule = $monitorgenerator->create_rule($rule);
543 $sub->ruleid = $createdrule->id;
544 $monitorgenerator->create_subscription($sub);
547 // Add 10 random rules for course 2.
548 $rule->courseid = $course2->id;
549 for ($i = 0; $i < 10; $i++) {
550 $createdrule = $monitorgenerator->create_rule($rule);
551 $sub->courseid = $rule->courseid;
552 $sub->ruleid = $createdrule->id;
553 $monitorgenerator->create_subscription($sub);
556 // Verify data before user delete.
557 $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
558 $this->assertCount(20, $totalrules);
559 $totalsubs = $DB->get_records('tool_monitor_subscriptions');
560 $this->assertCount(20, $totalsubs);
562 // Let us delete the user now.
563 delete_user($user);
565 // Verify data after course delete.
566 $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
567 $this->assertCount(20, $totalrules);
568 $totalsubs = $DB->get_records('tool_monitor_subscriptions');
569 $this->assertCount(0, $totalsubs); // Make sure all subscriptions are deleted.
573 * Test observer for course module delete event.
575 public function test_course_module_deleted() {
576 global $DB;
578 $this->setAdminUser();
579 $this->resetAfterTest(true);
581 $user = $this->getDataGenerator()->create_user();
582 $course1 = $this->getDataGenerator()->create_course();
583 $course2 = $this->getDataGenerator()->create_course();
584 $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
586 // Now let us create a rule specific to a module instance.
587 $cm = new stdClass();
588 $cm->course = $course1->id;
589 $book = $this->getDataGenerator()->create_module('book', $cm);
591 $rule = new stdClass();
592 $rule->userid = $user->id;
593 $rule->courseid = $course1->id;
594 $rule->plugin = 'test';
596 $sub = new stdClass();
597 $sub->courseid = $course1->id;
598 $sub->userid = $user->id;
599 $sub->cmid = $book->cmid;
601 // Add 10 rules for this course with subscriptions for this module.
602 for ($i = 0; $i < 10; $i++) {
603 $createdrule = $monitorgenerator->create_rule($rule);
604 $sub->ruleid = $createdrule->id;
605 $monitorgenerator->create_subscription($sub);
608 // Add 10 random rules for course 2.
609 $rule->courseid = $course2->id;
610 for ($i = 0; $i < 10; $i++) {
611 $createdrule = $monitorgenerator->create_rule($rule);
612 $sub->courseid = $rule->courseid;
613 $sub->ruleid = $createdrule->id;
614 $sub->cmid = 0;
615 $monitorgenerator->create_subscription($sub);
618 // Verify data before module delete.
619 $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
620 $this->assertCount(20, $totalrules);
621 $totalsubs = $DB->get_records('tool_monitor_subscriptions');
622 $this->assertCount(20, $totalsubs);
624 // Let us delete the user now.
625 course_delete_module($book->cmid);
627 // Verify data after course delete.
628 $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
629 $this->assertCount(20, $totalrules);
630 $totalsubs = $DB->get_records('tool_monitor_subscriptions');
631 $this->assertCount(10, $totalsubs); // Make sure only relevant subscriptions are deleted.