1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Events tests.
19 *
20 * @package    tool_monitor
21 * @category   test
22 * @copyright  2014 Mark Nelson <markn@moodle.com>
23 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28/**
29 * Tests that the tool_monitor events are valid and triggered correctly.
30 */
31class tool_monitor_events_testcase extends advanced_testcase {
32
33    /**
34     * Tests set up.
35     */
36    public function setUp() {
37        set_config('enablemonitor', 1, 'tool_monitor');
38        $this->resetAfterTest();
39    }
40
41    /**
42     * Test the rule created event.
43     */
44    public function test_rule_created() {
45        // Create the items we need to create a rule.
46        $course = $this->getDataGenerator()->create_course();
47        $user = $this->getDataGenerator()->create_user();
48
49        // Create the variables for the rule we want to create.
50        $ruledata = new stdClass();
51        $ruledata->userid = $user->id;
52        $ruledata->courseid = $course->id;
53        $ruledata->plugin = 'mod_assign';
54        $ruledata->eventname = '\mod_assign\event\submission_viewed';
55        $ruledata->description = 'Rule description';
56        $ruledata->descriptionformat = FORMAT_HTML;
57        $ruledata->template = 'A message template';
58        $ruledata->templateformat = FORMAT_HTML;
59        $ruledata->frequency = 1;
60        $ruledata->timewindow = 60;
61
62        // Trigger and capture the event.
63        $sink = $this->redirectEvents();
64        $rule = \tool_monitor\rule_manager::add_rule($ruledata);
65        $events = $sink->get_events();
66        $this->assertCount(1, $events);
67        $event = reset($events);
68
69        // Confirm that the event contains the expected values.
70        $this->assertInstanceOf('\tool_monitor\event\rule_created', $event);
71        $this->assertEquals(context_course::instance($course->id), $event->get_context());
72        $this->assertEquals($rule->id, $event->objectid);
73        $this->assertEventContextNotUsed($event);
74
75        // Now let's add a system rule (courseid = 0).
76        $ruledata->courseid = 0;
77
78        // Trigger and capture the event.
79        $sink = $this->redirectEvents();
80        \tool_monitor\rule_manager::add_rule($ruledata);
81        $events = $sink->get_events();
82        $this->assertCount(1, $events);
83        $event = reset($events);
84
85        // Confirm that the event uses the system context.
86        $this->assertInstanceOf('\tool_monitor\event\rule_created', $event);
87        $this->assertEquals(context_system::instance(), $event->get_context());
88    }
89
90    /**
91     * Test the rule updated event.
92     */
93    public function test_rule_updated() {
94        // Create the items we need.
95        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
96        $course = $this->getDataGenerator()->create_course();
97
98        // Create the rule we are going to update.
99        $createrule = new stdClass();
100        $createrule->courseid = $course->id;
101        $rule = $monitorgenerator->create_rule($createrule);
102
103        // Trigger and capture the event.
104        $sink = $this->redirectEvents();
105        $updaterule = new stdClass();
106        $updaterule->id = $rule->id;
107        \tool_monitor\rule_manager::update_rule($updaterule);
108        $events = $sink->get_events();
109        $this->assertCount(1, $events);
110        $event = reset($events);
111
112        // Confirm that the event contains the expected values.
113        $this->assertInstanceOf('\tool_monitor\event\rule_updated', $event);
114        $this->assertEquals(context_course::instance($course->id), $event->get_context());
115        $this->assertEquals($rule->id, $event->objectid);
116        $this->assertEventContextNotUsed($event);
117
118        // Now let's update a system rule (courseid = 0).
119        $createrule->courseid = 0;
120        $rule = $monitorgenerator->create_rule($createrule);
121
122        // Trigger and capture the event.
123        $sink = $this->redirectEvents();
124        $updaterule = new stdClass();
125        $updaterule->id = $rule->id;
126        \tool_monitor\rule_manager::update_rule($updaterule);
127        $events = $sink->get_events();
128        $this->assertCount(1, $events);
129        $event = reset($events);
130
131        // Confirm that the event uses the system context.
132        $this->assertInstanceOf('\tool_monitor\event\rule_updated', $event);
133        $this->assertEquals(context_system::instance(), $event->get_context());
134    }
135
136    /**
137     * Test the rule deleted event.
138     */
139    public function test_rule_deleted() {
140        // Create the items we need.
141        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
142        $course = $this->getDataGenerator()->create_course();
143
144        // Create the rule we are going to delete.
145        $createrule = new stdClass();
146        $createrule->courseid = $course->id;
147        $rule = $monitorgenerator->create_rule($createrule);
148
149        // Trigger and capture the event.
150        $sink = $this->redirectEvents();
151        \tool_monitor\rule_manager::delete_rule($rule->id);
152        $events = $sink->get_events();
153        $this->assertCount(1, $events);
154        $event = reset($events);
155
156        // Confirm that the event contains the expected values.
157        $this->assertInstanceOf('\tool_monitor\event\rule_deleted', $event);
158        $this->assertEquals(context_course::instance($course->id), $event->get_context());
159        $this->assertEquals($rule->id, $event->objectid);
160        $this->assertEventContextNotUsed($event);
161
162        // Now let's delete a system rule (courseid = 0).
163        $createrule = new stdClass();
164        $createrule->courseid = 0;
165        $rule = $monitorgenerator->create_rule($createrule);
166
167        // Trigger and capture the event.
168        $sink = $this->redirectEvents();
169        \tool_monitor\rule_manager::delete_rule($rule->id);
170        $events = $sink->get_events();
171        $this->assertCount(1, $events);
172        $event = reset($events);
173
174        // Confirm that the event uses the system context.
175        $this->assertInstanceOf('\tool_monitor\event\rule_deleted', $event);
176        $this->assertEquals(context_system::instance(), $event->get_context());
177    }
178
179    /**
180     * Test the subscription created event.
181     */
182    public function test_subscription_created() {
183        // Create the items we need to test this.
184        $user = $this->getDataGenerator()->create_user();
185        $course = $this->getDataGenerator()->create_course();
186        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
187
188        // Create a rule to subscribe to.
189        $rule = $monitorgenerator->create_rule();
190
191        // Trigger and capture the event.
192        $sink = $this->redirectEvents();
193        $subscriptionid = \tool_monitor\subscription_manager::create_subscription($rule->id, $course->id, 0, $user->id);
194        $events = $sink->get_events();
195        $this->assertCount(1, $events);
196        $event = reset($events);
197
198        // Confirm that the event contains the expected values.
199        $this->assertInstanceOf('\tool_monitor\event\subscription_created', $event);
200        $this->assertEquals(context_course::instance($course->id), $event->get_context());
201        $this->assertEquals($subscriptionid, $event->objectid);
202        $this->assertEventContextNotUsed($event);
203
204        // Create a system subscription - trigger and capture the event.
205        $sink = $this->redirectEvents();
206        \tool_monitor\subscription_manager::create_subscription($rule->id, 0, 0, $user->id);
207        $events = $sink->get_events();
208        $this->assertCount(1, $events);
209        $event = reset($events);
210
211        // Confirm that the event uses the system context.
212        $this->assertInstanceOf('\tool_monitor\event\subscription_created', $event);
213        $this->assertEquals(context_system::instance(), $event->get_context());
214    }
215
216    /**
217     * Test the subscription deleted event.
218     */
219    public function test_subscription_deleted() {
220        // Create the items we need to test this.
221        $user = $this->getDataGenerator()->create_user();
222        $course = $this->getDataGenerator()->create_course();
223        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
224
225        // Create a rule to subscribe to.
226        $rule = $monitorgenerator->create_rule();
227
228        $sub = new stdClass();
229        $sub->courseid = $course->id;
230        $sub->userid = $user->id;
231        $sub->ruleid = $rule->id;
232
233        // Create the subscription we are going to delete.
234        $subscription = $monitorgenerator->create_subscription($sub);
235
236        // Trigger and capture the event.
237        $sink = $this->redirectEvents();
238        \tool_monitor\subscription_manager::delete_subscription($subscription->id, false);
239        $events = $sink->get_events();
240        $this->assertCount(1, $events);
241        $event = reset($events);
242
243        // Confirm that the event contains the expected values.
244        $this->assertInstanceOf('\tool_monitor\event\subscription_deleted', $event);
245        $this->assertEquals(context_course::instance($course->id), $event->get_context());
246        $this->assertEquals($subscription->id, $event->objectid);
247        $this->assertEventContextNotUsed($event);
248
249        // Now let's delete a system subscription.
250        $sub = new stdClass();
251        $sub->courseid = 0;
252        $sub->userid = $user->id;
253        $sub->ruleid = $rule->id;
254
255        // Create the subscription we are going to delete.
256        $subscription = $monitorgenerator->create_subscription($sub);
257
258        // Trigger and capture the event.
259        $sink = $this->redirectEvents();
260        \tool_monitor\subscription_manager::delete_subscription($subscription->id, false);
261        $events = $sink->get_events();
262        $this->assertCount(1, $events);
263        $event = reset($events);
264
265        // Confirm that the event uses the system context.
266        $this->assertInstanceOf('\tool_monitor\event\subscription_deleted', $event);
267        $this->assertEquals(context_system::instance(), $event->get_context());
268
269        // Now, create a bunch of subscriptions for the rule we created.
270        $subids = array();
271        $sub->courseid = $course->id;
272        for ($i = 1; $i <= 10; $i++) {
273            $sub->userid = $i;
274            $subscription = $monitorgenerator->create_subscription($sub);
275            $subids[$subscription->id] = $subscription;
276        }
277
278        // Trigger and capture the events.
279        $sink = $this->redirectEvents();
280        \tool_monitor\subscription_manager::remove_all_subscriptions_for_rule($rule->id);
281        $events = $sink->get_events();
282
283        // Check that there were 10 events in total.
284        $this->assertCount(10, $events);
285
286        // Get all the events and ensure they are valid.
287        foreach ($events as $event) {
288            $this->assertInstanceOf('\tool_monitor\event\subscription_deleted', $event);
289            $this->assertEquals(context_course::instance($course->id), $event->get_context());
290            $this->assertEventContextNotUsed($event);
291            $this->assertArrayHasKey($event->objectid, $subids);
292            unset($subids[$event->objectid]);
293        }
294
295        // We should have found all the subscriptions.
296        $this->assertEmpty($subids);
297    }
298
299    /**
300     * Test the subscription criteria met event.
301     */
302    public function test_subscription_criteria_met() {
303        // Create the items we need to test this.
304        $user = $this->getDataGenerator()->create_user();
305        $course = $this->getDataGenerator()->create_course();
306        $book = $this->getDataGenerator()->create_module('book', array('course' => $course->id));
307        $bookgenerator = $this->getDataGenerator()->get_plugin_generator('mod_book');
308        $chapter = $bookgenerator->create_chapter(array('bookid' => $book->id));
309        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
310
311        // Create a rule we want to subscribe to.
312        $rule = new stdClass();
313        $rule->userid = $user->id;
314        $rule->courseid = $course->id;
315        $rule->plugin = 'mod_book';
316        $rule->eventname = '\mod_book\event\chapter_viewed';
317        $rule->frequency = 1;
318        $rule->timewindow = 60;
319        $rule = $monitorgenerator->create_rule($rule);
320
321        // Create the subscription.
322        $sub = new stdClass();
323        $sub->courseid = $course->id;
324        $sub->userid = $user->id;
325        $sub->ruleid = $rule->id;
326        $monitorgenerator->create_subscription($sub);
327
328        // Now create the \mod_book\event\chapter_viewed event we are listening for.
329        $context = context_module::instance($book->cmid);
330        $event = \mod_book\event\chapter_viewed::create_from_chapter($book, $context, $chapter);
331
332        // Trigger and capture the event.
333        $sink = $this->redirectEvents();
334        \tool_monitor\eventobservers::process_event($event);
335        $events = $sink->get_events();
336        $this->assertCount(1, $events);
337        $event = reset($events);
338
339        // Confirm that the event contains the expected values.
340        $this->assertInstanceOf('\tool_monitor\event\subscription_criteria_met', $event);
341        $this->assertEquals(context_course::instance($course->id), $event->get_context());
342        $this->assertEventContextNotUsed($event);
343    }
344}
345