1133738d84b6698225bce3cbf0ec8c306f4770de
[moodle.git] / question / tests / events_test.php
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/>.
17 /**
18  * Events tests.
19  *
20  * @package core_question
21  * @copyright 2014 Mark Nelson <markn@moodle.com>
22  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
27 global $CFG;
29 require_once($CFG->dirroot . '/question/editlib.php');
30 require_once($CFG->dirroot . '/question/category_class.php');
32 class core_question_events_testcase extends advanced_testcase {
34     /**
35      * Tests set up.
36      */
37     public function setUp() {
38         $this->resetAfterTest();
39     }
41     /**
42      * Test the question category created event.
43      */
44     public function test_question_category_created() {
45         $this->setAdminUser();
46         $course = $this->getDataGenerator()->create_course();
47         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
49         $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
51         $defaultcategoryobj = question_make_default_categories(array($contexts->lowest()));
52         $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
54         $qcobject = new question_category_object(
55             1,
56             new moodle_url('/mod/quiz/edit.php', array('cmid' => $quiz->cmid)),
57             $contexts->having_one_edit_tab_cap('categories'),
58             $defaultcategoryobj->id,
59             $defaultcategory,
60             null,
61             $contexts->having_cap('moodle/question:add'));
63         // Trigger and capture the event.
64         $sink = $this->redirectEvents();
65         $categoryid = $qcobject->add_category($defaultcategory, 'newcategory', '', true);
66         $events = $sink->get_events();
67         $event = reset($events);
69         // Check that the event data is valid.
70         $this->assertInstanceOf('\core\event\question_category_created', $event);
71         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
72         $expected = array($course->id, 'quiz', 'addcategory', 'view.php?id=' . $quiz->cmid , $categoryid, $quiz->cmid);
73         $this->assertEventLegacyLogData($expected, $event);
74         $this->assertEventContextNotUsed($event);
75     }
77     /**
78      * Test the question category deleted event.
79      */
80     public function test_question_category_deleted() {
81         $this->setAdminUser();
82         $course = $this->getDataGenerator()->create_course();
83         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
85         $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
87         $defaultcategoryobj = question_make_default_categories(array($contexts->lowest()));
88         $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
90         $qcobject = new question_category_object(
91             1,
92             new moodle_url('/mod/quiz/edit.php', array('cmid' => $quiz->cmid)),
93             $contexts->having_one_edit_tab_cap('categories'),
94             $defaultcategoryobj->id,
95             $defaultcategory,
96             null,
97             $contexts->having_cap('moodle/question:add'));
99         // Create the category.
100         $categoryid = $qcobject->add_category($defaultcategory, 'newcategory', '', true);
102         // Trigger and capture the event.
103         $sink = $this->redirectEvents();
104         $qcobject->delete_category($categoryid);
105         $events = $sink->get_events();
106         $event = reset($events);
108         // Check that the event data is valid.
109         $this->assertInstanceOf('\core\event\question_category_deleted', $event);
110         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
111         $this->assertEquals($categoryid, $event->objectid);
112         $this->assertDebuggingNotCalled();
113     }
115     /**
116      * Test the question category updated event.
117      */
118     public function test_question_category_updated() {
119         $this->setAdminUser();
120         $course = $this->getDataGenerator()->create_course();
121         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
123         $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
125         $defaultcategoryobj = question_make_default_categories(array($contexts->lowest()));
126         $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
128         $qcobject = new question_category_object(
129             1,
130             new moodle_url('/mod/quiz/edit.php', array('cmid' => $quiz->cmid)),
131             $contexts->having_one_edit_tab_cap('categories'),
132             $defaultcategoryobj->id,
133             $defaultcategory,
134             null,
135             $contexts->having_cap('moodle/question:add'));
137         // Create the category.
138         $categoryid = $qcobject->add_category($defaultcategory, 'newcategory', '', true);
140         // Trigger and capture the event.
141         $sink = $this->redirectEvents();
142         $qcobject->update_category($categoryid, $defaultcategory, 'updatedcategory', '', FORMAT_HTML, '', false);
143         $events = $sink->get_events();
144         $event = reset($events);
146         // Check that the event data is valid.
147         $this->assertInstanceOf('\core\event\question_category_updated', $event);
148         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
149         $this->assertEquals($categoryid, $event->objectid);
150         $this->assertDebuggingNotCalled();
151     }
153     /**
154      * Test the question category viewed event.
155      * There is no external API for viewing the category, so the unit test will simply
156      * create and trigger the event and ensure data is returned as expected.
157      */
158     public function test_question_category_viewed() {
160         $this->setAdminUser();
161         $course = $this->getDataGenerator()->create_course();
162         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
164         $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
166         $defaultcategoryobj = question_make_default_categories(array($contexts->lowest()));
167         $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
169         $qcobject = new question_category_object(
170             1,
171             new moodle_url('/mod/quiz/edit.php', array('cmid' => $quiz->cmid)),
172             $contexts->having_one_edit_tab_cap('categories'),
173             $defaultcategoryobj->id,
174             $defaultcategory,
175             null,
176             $contexts->having_cap('moodle/question:add'));
178         // Create the category.
179         $categoryid = $qcobject->add_category($defaultcategory, 'newcategory', '', true);
181         // Log the view of this category.
182         $params = array(
183             'objectid' => $categoryid,
184             'context' => context_module::instance($quiz->cmid)
185         );
187         $event = \core\event\question_category_viewed::create($params);
189         // Trigger and capture the event.
190         $sink = $this->redirectEvents();
191         $event->trigger();
192         $events = $sink->get_events();
193         $event = reset($events);
195         // Check that the event data is valid.
196         $this->assertInstanceOf('\core\event\question_category_viewed', $event);
197         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
198         $this->assertEquals($categoryid, $event->objectid);
199         $this->assertDebuggingNotCalled();
201     }
203     /**
204      * Test the questions imported event.
205      * There is no easy way to trigger this event using the API, so the unit test will simply
206      * create and trigger the event and ensure data is returned as expected.
207      */
208     public function test_questions_imported() {
210         $this->setAdminUser();
211         $course = $this->getDataGenerator()->create_course();
212         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
214         $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
216         $defaultcategoryobj = question_make_default_categories(array($contexts->lowest()));
217         $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
219         $qcobject = new question_category_object(
220             1,
221             new moodle_url('/mod/quiz/edit.php', array('cmid' => $quiz->cmid)),
222             $contexts->having_one_edit_tab_cap('categories'),
223             $defaultcategoryobj->id,
224             $defaultcategory,
225             null,
226             $contexts->having_cap('moodle/question:add'));
228         // Create the category.
229         $categoryid = $qcobject->add_category($defaultcategory, 'newcategory', '', true);
231         // Log the view of this category.
232         $params = array(
233             'context' => context_module::instance($quiz->cmid),
234             'other' => array('categoryid' => $categoryid, 'format' => 'testformat')
235         );
237         $event = \core\event\questions_imported::create($params);
239         // Trigger and capture the event.
240         $sink = $this->redirectEvents();
241         $event->trigger();
242         $events = $sink->get_events();
243         $event = reset($events);
245         // Check that the event data is valid.
246         $this->assertInstanceOf('\core\event\questions_imported', $event);
247         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
248         $this->assertEquals($categoryid, $event->other['categoryid']);
249         $this->assertEquals('testformat', $event->other['format']);
250         $this->assertDebuggingNotCalled();
252     }
254     /**
255      * Test the questions exported event.
256      * There is no easy way to trigger this event using the API, so the unit test will simply
257      * create and trigger the event and ensure data is returned as expected.
258      */
259     public function test_questions_exported() {
261         $this->setAdminUser();
262         $course = $this->getDataGenerator()->create_course();
263         $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
265         $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
267         $defaultcategoryobj = question_make_default_categories(array($contexts->lowest()));
268         $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
270         $qcobject = new question_category_object(
271             1,
272             new moodle_url('/mod/quiz/edit.php', array('cmid' => $quiz->cmid)),
273             $contexts->having_one_edit_tab_cap('categories'),
274             $defaultcategoryobj->id,
275             $defaultcategory,
276             null,
277             $contexts->having_cap('moodle/question:add'));
279         // Create the category.
280         $categoryid = $qcobject->add_category($defaultcategory, 'newcategory', '', true);
282         // Log the view of this category.
283         $params = array(
284             'context' => context_module::instance($quiz->cmid),
285             'other' => array('categoryid' => $categoryid, 'format' => 'testformat')
286         );
288         $event = \core\event\questions_exported::create($params);
290         // Trigger and capture the event.
291         $sink = $this->redirectEvents();
292         $event->trigger();
293         $events = $sink->get_events();
294         $event = reset($events);
296         // Check that the event data is valid.
297         $this->assertInstanceOf('\core\event\questions_exported', $event);
298         $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
299         $this->assertEquals($categoryid, $event->other['categoryid']);
300         $this->assertEquals('testformat', $event->other['format']);
301         $this->assertDebuggingNotCalled();
303     }
305     /**
306      * Test the question created event.
307      */
308     public function test_question_created() {
310         $this->setAdminUser();
311         $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
313         $cat = $generator->create_question_category(array(
314                 'name' => 'My category', 'sortorder' => 1));
316         // Trigger and capture the event.
317         $sink = $this->redirectEvents();
318         $questiondata = $generator->create_question('description', null, array('category' => $cat->id));
319         $question = question_bank::load_question($questiondata->id);
321         $events = $sink->get_events();
322         $event = reset($events);
324         // Check that the event data is valid.
325         $this->assertInstanceOf('\core\event\question_created', $event);
326         $this->assertEquals($question->id, $event->objectid);
327         $this->assertEquals($cat->id, $event->other['categoryid']);
328         $this->assertDebuggingNotCalled();
330     }
332     /**
333      * Test the question deleted event.
334      */
335     public function test_question_deleted() {
337         $this->setAdminUser();
338         $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
340         $cat = $generator->create_question_category(array(
341                 'name' => 'My category', 'sortorder' => 1));
343         $questiondata = $generator->create_question('description', null, array('category' => $cat->id));
344         $question = question_bank::load_question($questiondata->id);
346         // Trigger and capture the event.
347         $sink = $this->redirectEvents();
348         question_delete_question($question->id);
349         $events = $sink->get_events();
350         $event = reset($events);
352         // Check that the event data is valid.
353         $this->assertInstanceOf('\core\event\question_deleted', $event);
354         $this->assertEquals($question->id, $event->objectid);
355         $this->assertEquals($cat->id, $event->other['categoryid']);
356         $this->assertDebuggingNotCalled();
358     }
360     /**
361      * Test the question updated event.
362      */
363     public function test_question_updated() {
365         global $CFG;
366         require_once($CFG->dirroot . '/question/type/description/questiontype.php');
367         require_once($CFG->dirroot . '/question/type/edit_question_form.php');
368         require_once($CFG->dirroot . '/question/type/description/edit_description_form.php');
370         $this->setAdminUser();
371         $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
373         $cat = $generator->create_question_category(array(
374                 'name' => 'My category', 'sortorder' => 1));
376         $questiondata = $generator->create_question('description', null, array('category' => $cat->id));
377         $question = question_bank::load_question($questiondata->id);
379         $qtype = new qtype_description();
380         $formdata = test_question_maker::get_question_form_data('description');
381         $formdata->category = "{$cat->id},{$cat->contextid}";
382         qtype_description_edit_form::mock_submit((array)$formdata);
384         $form = qtype_description_test_helper::get_question_editing_form($cat, $questiondata);
385         $fromform = $form->get_data();
387         // Trigger and capture the event.
388         $sink = $this->redirectEvents();
389         $qtype->save_question($questiondata, $fromform);
390         $events = $sink->get_events();
391         $event = reset($events);
393         // Check that the event data is valid.
394         $this->assertInstanceOf('\core\event\question_updated', $event);
395         $this->assertEquals($question->id, $event->objectid);
396         $this->assertEquals($cat->id, $event->other['categoryid']);
397         $this->assertDebuggingNotCalled();
399     }
401     /**
402      * Test the question moved event.
403      */
404     public function test_question_moved() {
406         $this->setAdminUser();
407         $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
409         $cat1 = $generator->create_question_category(array(
410                 'name' => 'My category 1', 'sortorder' => 1));
412         $cat2 = $generator->create_question_category(array(
413                 'name' => 'My category 2', 'sortorder' => 2));
415         $questiondata = $generator->create_question('description', null, array('category' => $cat1->id));
416         $question = question_bank::load_question($questiondata->id);
418         // Trigger and capture the event.
419         $sink = $this->redirectEvents();
420         question_move_questions_to_category(array($question->id), $cat2->id);
421         $events = $sink->get_events();
422         $event = reset($events);
424         // Check that the event data is valid.
425         $this->assertInstanceOf('\core\event\question_moved', $event);
426         $this->assertEquals($question->id, $event->objectid);
427         $this->assertEquals($cat1->id, $event->other['oldcategoryid']);
428         $this->assertEquals($cat2->id, $event->other['newcategoryid']);
429         $this->assertDebuggingNotCalled();
431     }
433     /**
434      * Test the question viewed event.
435      * There is no external API for viewing the question, so the unit test will simply
436      * create and trigger the event and ensure data is returned as expected.
437      */
438     public function test_question_viewed() {
440         $this->setAdminUser();
441         $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
443         $cat = $generator->create_question_category(array(
444                 'name' => 'My category', 'sortorder' => 1));
446         $questiondata = $generator->create_question('description', null, array('category' => $cat->id));
447         $question = question_bank::load_question($questiondata->id);
449         $params = array(
450             'objectid' => $question->id,
451             'context' => context::instance_by_id($cat->contextid),
452             'other' => array('categoryid' => $question->category)
453         );
455         $event = \core\event\question_previewed::create($params);
457         // Trigger and capture the event.
458         $sink = $this->redirectEvents();
459         $event->trigger();
460         $events = $sink->get_events();
461         $event = reset($events);
463         // Check that the event data is valid.
464         $this->assertInstanceOf('\core\event\question_previewed', $event);
465         $this->assertEquals($question->id, $event->objectid);
466         $this->assertEquals($cat->id, $event->other['categoryid']);
467         $this->assertDebuggingNotCalled();
469     }