Merge branch 'MDL-66801' of https://github.com/timhunt/moodle
[moodle.git] / question / tests / events_test.php
blob0f93b8605f92d5b13ed1925d81db1b5ff72d4f1e
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 * Events tests.
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
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.
37 public function setUp() {
38 $this->resetAfterTest();
41 /**
42 * Test the question category created event.
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(
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);
77 /**
78 * Test the question category deleted event.
80 public function test_question_category_deleted() {
81 $this->setAdminUser();
82 $course = $this->getDataGenerator()->create_course();
83 $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
85 $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
87 $defaultcategoryobj = question_make_default_categories([$contexts->lowest()]);
88 $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
90 $qcobject = new question_category_object(
92 new moodle_url('/mod/quiz/edit.php', ['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();
116 * Test the question category updated event.
118 public function test_question_category_updated() {
119 $this->setAdminUser();
120 $course = $this->getDataGenerator()->create_course();
121 $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
123 $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
125 $defaultcategoryobj = question_make_default_categories([$contexts->lowest()]);
126 $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
128 $qcobject = new question_category_object(
130 new moodle_url('/mod/quiz/edit.php', ['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();
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.
158 public function test_question_category_viewed() {
160 $this->setAdminUser();
161 $course = $this->getDataGenerator()->create_course();
162 $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
164 $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
166 $defaultcategoryobj = question_make_default_categories([$contexts->lowest()]);
167 $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
169 $qcobject = new question_category_object(
171 new moodle_url('/mod/quiz/edit.php', ['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 $category = new stdClass();
183 $category->id = $categoryid;
184 $context = context_module::instance($quiz->cmid);
185 $event = \core\event\question_category_viewed::create_from_question_category_instance($category, $context);
187 // Trigger and capture the event.
188 $sink = $this->redirectEvents();
189 $event->trigger();
190 $events = $sink->get_events();
191 $event = reset($events);
193 // Check that the event data is valid.
194 $this->assertInstanceOf('\core\event\question_category_viewed', $event);
195 $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
196 $this->assertEquals($categoryid, $event->objectid);
197 $this->assertDebuggingNotCalled();
202 * Test the questions imported event.
203 * There is no easy way to trigger this event using the API, so the unit test will simply
204 * create and trigger the event and ensure data is returned as expected.
206 public function test_questions_imported() {
208 $this->setAdminUser();
209 $course = $this->getDataGenerator()->create_course();
210 $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
212 $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
214 $defaultcategoryobj = question_make_default_categories([$contexts->lowest()]);
215 $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
217 $qcobject = new question_category_object(
219 new moodle_url('/mod/quiz/edit.php', ['cmid' => $quiz->cmid]),
220 $contexts->having_one_edit_tab_cap('categories'),
221 $defaultcategoryobj->id,
222 $defaultcategory,
223 null,
224 $contexts->having_cap('moodle/question:add'));
226 // Create the category.
227 $categoryid = $qcobject->add_category($defaultcategory, 'newcategory', '', true);
229 // Log the view of this category.
230 $params = [
231 'context' => context_module::instance($quiz->cmid),
232 'other' => ['categoryid' => $categoryid, 'format' => 'testformat'],
235 $event = \core\event\questions_imported::create($params);
237 // Trigger and capture the event.
238 $sink = $this->redirectEvents();
239 $event->trigger();
240 $events = $sink->get_events();
241 $event = reset($events);
243 // Check that the event data is valid.
244 $this->assertInstanceOf('\core\event\questions_imported', $event);
245 $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
246 $this->assertEquals($categoryid, $event->other['categoryid']);
247 $this->assertEquals('testformat', $event->other['format']);
248 $this->assertDebuggingNotCalled();
253 * Test the questions exported event.
254 * There is no easy way to trigger this event using the API, so the unit test will simply
255 * create and trigger the event and ensure data is returned as expected.
257 public function test_questions_exported() {
259 $this->setAdminUser();
260 $course = $this->getDataGenerator()->create_course();
261 $quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
263 $contexts = new question_edit_contexts(context_module::instance($quiz->cmid));
265 $defaultcategoryobj = question_make_default_categories([$contexts->lowest()]);
266 $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
268 $qcobject = new question_category_object(
270 new moodle_url('/mod/quiz/edit.php', ['cmid' => $quiz->cmid]),
271 $contexts->having_one_edit_tab_cap('categories'),
272 $defaultcategoryobj->id,
273 $defaultcategory,
274 null,
275 $contexts->having_cap('moodle/question:add'));
277 // Create the category.
278 $categoryid = $qcobject->add_category($defaultcategory, 'newcategory', '', true);
280 // Log the view of this category.
281 $params = [
282 'context' => context_module::instance($quiz->cmid),
283 'other' => ['categoryid' => $categoryid, 'format' => 'testformat'],
286 $event = \core\event\questions_exported::create($params);
288 // Trigger and capture the event.
289 $sink = $this->redirectEvents();
290 $event->trigger();
291 $events = $sink->get_events();
292 $event = reset($events);
294 // Check that the event data is valid.
295 $this->assertInstanceOf('\core\event\questions_exported', $event);
296 $this->assertEquals(context_module::instance($quiz->cmid), $event->get_context());
297 $this->assertEquals($categoryid, $event->other['categoryid']);
298 $this->assertEquals('testformat', $event->other['format']);
299 $this->assertDebuggingNotCalled();
304 * Test the question created event.
306 public function test_question_created() {
308 $this->setAdminUser();
309 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
311 $cat = $generator->create_question_category(['name' => 'My category', 'sortorder' => 1]);
313 // Trigger and capture the event.
314 $sink = $this->redirectEvents();
315 $questiondata = $generator->create_question('description', null, ['category' => $cat->id]);
316 $question = question_bank::load_question($questiondata->id);
318 $events = $sink->get_events();
319 $event = reset($events);
321 // Check that the event data is valid.
322 $this->assertInstanceOf('\core\event\question_created', $event);
323 $this->assertEquals($question->id, $event->objectid);
324 $this->assertEquals($cat->id, $event->other['categoryid']);
325 $this->assertDebuggingNotCalled();
330 * Test the question deleted event.
332 public function test_question_deleted() {
334 $this->setAdminUser();
335 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
337 $cat = $generator->create_question_category(['name' => 'My category', 'sortorder' => 1]);
339 $questiondata = $generator->create_question('description', null, ['category' => $cat->id]);
340 $question = question_bank::load_question($questiondata->id);
342 // Trigger and capture the event.
343 $sink = $this->redirectEvents();
344 question_delete_question($question->id);
345 $events = $sink->get_events();
346 $event = reset($events);
348 // Check that the event data is valid.
349 $this->assertInstanceOf('\core\event\question_deleted', $event);
350 $this->assertEquals($question->id, $event->objectid);
351 $this->assertEquals($cat->id, $event->other['categoryid']);
352 $this->assertDebuggingNotCalled();
357 * Test the question updated event.
359 public function test_question_updated() {
361 global $CFG;
362 require_once($CFG->dirroot . '/question/type/description/questiontype.php');
363 require_once($CFG->dirroot . '/question/type/edit_question_form.php');
364 require_once($CFG->dirroot . '/question/type/description/edit_description_form.php');
366 $this->setAdminUser();
367 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
369 $cat = $generator->create_question_category(['name' => 'My category', 'sortorder' => 1]);
371 $questiondata = $generator->create_question('description', null, ['category' => $cat->id]);
372 $question = question_bank::load_question($questiondata->id);
374 $qtype = new qtype_description();
375 $formdata = test_question_maker::get_question_form_data('description');
376 $formdata->category = "{$cat->id},{$cat->contextid}";
377 qtype_description_edit_form::mock_submit((array) $formdata);
379 $form = qtype_description_test_helper::get_question_editing_form($cat, $questiondata);
380 $fromform = $form->get_data();
382 // Trigger and capture the event.
383 $sink = $this->redirectEvents();
384 $qtype->save_question($questiondata, $fromform);
385 $events = $sink->get_events();
386 $event = reset($events);
388 // Check that the event data is valid.
389 $this->assertInstanceOf('\core\event\question_updated', $event);
390 $this->assertEquals($question->id, $event->objectid);
391 $this->assertEquals($cat->id, $event->other['categoryid']);
392 $this->assertDebuggingNotCalled();
397 * Test the question moved event.
399 public function test_question_moved() {
401 $this->setAdminUser();
402 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
404 $cat1 = $generator->create_question_category([
405 'name' => 'My category 1', 'sortorder' => 1]);
407 $cat2 = $generator->create_question_category([
408 'name' => 'My category 2', 'sortorder' => 2]);
410 $questiondata = $generator->create_question('description', null, ['category' => $cat1->id]);
411 $question = question_bank::load_question($questiondata->id);
413 // Trigger and capture the event.
414 $sink = $this->redirectEvents();
415 question_move_questions_to_category([$question->id], $cat2->id);
416 $events = $sink->get_events();
417 $event = reset($events);
419 // Check that the event data is valid.
420 $this->assertInstanceOf('\core\event\question_moved', $event);
421 $this->assertEquals($question->id, $event->objectid);
422 $this->assertEquals($cat1->id, $event->other['oldcategoryid']);
423 $this->assertEquals($cat2->id, $event->other['newcategoryid']);
424 $this->assertDebuggingNotCalled();
429 * Test the question viewed event.
430 * There is no external API for viewing the question, so the unit test will simply
431 * create and trigger the event and ensure data is returned as expected.
433 public function test_question_viewed() {
435 $this->setAdminUser();
436 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
438 $cat = $generator->create_question_category(['name' => 'My category', 'sortorder' => 1]);
440 $questiondata = $generator->create_question('description', null, ['category' => $cat->id]);
441 $question = question_bank::load_question($questiondata->id);
443 $event = \core\event\question_viewed::create_from_question_instance($question, context::instance_by_id($cat->contextid));
445 // Trigger and capture the event.
446 $sink = $this->redirectEvents();
447 $event->trigger();
448 $events = $sink->get_events();
449 $event = reset($events);
451 // Check that the event data is valid.
452 $this->assertInstanceOf('\core\event\question_viewed', $event);
453 $this->assertEquals($question->id, $event->objectid);
454 $this->assertEquals($cat->id, $event->other['categoryid']);
455 $this->assertDebuggingNotCalled();