Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 311 and 403] [Versions 400 and 403] [Versions 401 and 403]

   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   * Tests for feedback events.
  19   *
  20   * @package    mod_feedback
  21   * @copyright  2013 Ankit Agarwal
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
  23   */
  24  
  25  namespace mod_feedback\event;
  26  
  27  /**
  28   * Class mod_feedback_events_testcase
  29   *
  30   * Class for tests related to feedback events.
  31   *
  32   * @package    mod_feedback
  33   * @copyright  2013 Ankit Agarwal
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
  35   */
  36  class events_test extends \advanced_testcase {
  37  
  38      /** @var  stdClass A user who likes to interact with feedback activity. */
  39      private $eventuser;
  40  
  41      /** @var  stdClass A course used to hold feedback activities for testing. */
  42      private $eventcourse;
  43  
  44      /** @var  stdClass A feedback activity used for feedback event testing. */
  45      private $eventfeedback;
  46  
  47      /** @var  stdClass course module object . */
  48      private $eventcm;
  49  
  50      /** @var  stdClass A feedback item. */
  51      private $eventfeedbackitem;
  52  
  53      /** @var  stdClass A feedback activity response submitted by user. */
  54      private $eventfeedbackcompleted;
  55  
  56      /** @var  stdClass value associated with $eventfeedbackitem . */
  57      private $eventfeedbackvalue;
  58  
  59      public function setUp(): void {
  60          global $DB;
  61  
  62          $this->setAdminUser();
  63          $gen = $this->getDataGenerator();
  64          $this->eventuser = $gen->create_user(); // Create a user.
  65          $course = $gen->create_course(); // Create a course.
  66          // Assign manager role, so user can see reports.
  67          role_assign(1, $this->eventuser->id, \context_course::instance($course->id));
  68  
  69          // Add a feedback activity to the created course.
  70          $record = new \stdClass();
  71          $record->course = $course->id;
  72          $feedback = $gen->create_module('feedback', $record);
  73          $this->eventfeedback = $DB->get_record('feedback', array('id' => $feedback->id), '*', MUST_EXIST); // Get exact copy.
  74          $this->eventcm = get_coursemodule_from_instance('feedback', $this->eventfeedback->id, false, MUST_EXIST);
  75  
  76          // Create a feedback item.
  77          $item = new \stdClass();
  78          $item->feedback = $this->eventfeedback->id;
  79          $item->type = 'numeric';
  80          $item->presentation = '0|0';
  81          $itemid = $DB->insert_record('feedback_item', $item);
  82          $this->eventfeedbackitem = $DB->get_record('feedback_item', array('id' => $itemid), '*', MUST_EXIST);
  83  
  84          // Create a response from a user.
  85          $response = new \stdClass();
  86          $response->feedback = $this->eventfeedback->id;
  87          $response->userid = $this->eventuser->id;
  88          $response->anonymous_response = FEEDBACK_ANONYMOUS_YES;
  89          $completedid = $DB->insert_record('feedback_completed', $response);
  90          $this->eventfeedbackcompleted = $DB->get_record('feedback_completed', array('id' => $completedid), '*', MUST_EXIST);
  91  
  92          $value = new \stdClass();
  93          $value->course_id = $course->id;
  94          $value->item = $this->eventfeedbackitem->id;
  95          $value->completed = $this->eventfeedbackcompleted->id;
  96          $value->value = 25; // User response value.
  97          $valueid = $DB->insert_record('feedback_value', $value);
  98          $this->eventfeedbackvalue = $DB->get_record('feedback_value', array('id' => $valueid), '*', MUST_EXIST);
  99          // Do this in the end to get correct sortorder and cacherev values.
 100          $this->eventcourse = $DB->get_record('course', array('id' => $course->id), '*', MUST_EXIST);
 101  
 102      }
 103  
 104      /**
 105       * Tests for event response_deleted.
 106       */
 107      public function test_response_deleted_event() {
 108          global $USER, $DB;
 109          $this->resetAfterTest();
 110  
 111          // Create and delete a module.
 112          $sink = $this->redirectEvents();
 113          feedback_delete_completed($this->eventfeedbackcompleted->id);
 114          $events = $sink->get_events();
 115          $event = array_pop($events); // Delete feedback event.
 116          $sink->close();
 117  
 118          // Validate event data.
 119          $this->assertInstanceOf('\mod_feedback\event\response_deleted', $event);
 120          $this->assertEquals($this->eventfeedbackcompleted->id, $event->objectid);
 121          $this->assertEquals($USER->id, $event->userid);
 122          $this->assertEquals($this->eventuser->id, $event->relateduserid);
 123          $this->assertEquals('feedback_completed', $event->objecttable);
 124          $this->assertEquals(null, $event->get_url());
 125          $this->assertEquals($this->eventfeedbackcompleted, $event->get_record_snapshot('feedback_completed', $event->objectid));
 126          $this->assertEquals($this->eventcourse, $event->get_record_snapshot('course', $event->courseid));
 127          $this->assertEquals($this->eventfeedback, $event->get_record_snapshot('feedback', $event->other['instanceid']));
 128  
 129          // Test can_view() .
 130          $this->setUser($this->eventuser);
 131          $this->assertFalse($event->can_view());
 132          $this->assertDebuggingCalled();
 133          $this->setAdminUser();
 134          $this->assertTrue($event->can_view());
 135          $this->assertDebuggingCalled();
 136  
 137          // Create a response, with anonymous set to no and test can_view().
 138          $response = new \stdClass();
 139          $response->feedback = $this->eventcm->instance;
 140          $response->userid = $this->eventuser->id;
 141          $response->anonymous_response = FEEDBACK_ANONYMOUS_NO;
 142          $completedid = $DB->insert_record('feedback_completed', $response);
 143          $DB->get_record('feedback_completed', array('id' => $completedid), '*', MUST_EXIST);
 144          $value = new \stdClass();
 145          $value->course_id = $this->eventcourse->id;
 146          $value->item = $this->eventfeedbackitem->id;
 147          $value->completed = $completedid;
 148          $value->value = 25; // User response value.
 149          $DB->insert_record('feedback_valuetmp', $value);
 150  
 151          // Save the feedback.
 152          $sink = $this->redirectEvents();
 153          feedback_delete_completed($completedid);
 154          $events = $sink->get_events();
 155          $event = array_pop($events); // Response submitted feedback event.
 156          $sink->close();
 157  
 158          // Test can_view() .
 159          $this->setUser($this->eventuser);
 160          $this->assertTrue($event->can_view());
 161          $this->assertDebuggingCalled();
 162          $this->setAdminUser();
 163          $this->assertTrue($event->can_view());
 164          $this->assertDebuggingCalled();
 165          $this->assertEventContextNotUsed($event);
 166      }
 167  
 168      /**
 169       * Tests for event validations related to feedback response deletion.
 170       */
 171      public function test_response_deleted_event_exceptions() {
 172  
 173          $this->resetAfterTest();
 174  
 175          $context = \context_module::instance($this->eventcm->id);
 176  
 177          // Test not setting other['anonymous'].
 178          try {
 179              \mod_feedback\event\response_submitted::create(array(
 180                  'context'  => $context,
 181                  'objectid' => $this->eventfeedbackcompleted->id,
 182                  'relateduserid' => 2,
 183              ));
 184              $this->fail("Event validation should not allow \\mod_feedback\\event\\response_deleted to be triggered without
 185                      other['anonymous']");
 186          } catch (\coding_exception $e) {
 187              $this->assertStringContainsString("The 'anonymous' value must be set in other.", $e->getMessage());
 188          }
 189      }
 190  
 191      /**
 192       * Tests for event response_submitted.
 193       */
 194      public function test_response_submitted_event() {
 195          global $USER, $DB;
 196          $this->resetAfterTest();
 197          $this->setUser($this->eventuser);
 198  
 199          // Create a temporary response, with anonymous set to yes.
 200          $response = new \stdClass();
 201          $response->feedback = $this->eventcm->instance;
 202          $response->userid = $this->eventuser->id;
 203          $response->anonymous_response = FEEDBACK_ANONYMOUS_YES;
 204          $completedid = $DB->insert_record('feedback_completedtmp', $response);
 205          $completed = $DB->get_record('feedback_completedtmp', array('id' => $completedid), '*', MUST_EXIST);
 206          $value = new \stdClass();
 207          $value->course_id = $this->eventcourse->id;
 208          $value->item = $this->eventfeedbackitem->id;
 209          $value->completed = $completedid;
 210          $value->value = 25; // User response value.
 211          $DB->insert_record('feedback_valuetmp', $value);
 212  
 213          // Save the feedback.
 214          $sink = $this->redirectEvents();
 215          $id = feedback_save_tmp_values($completed, false);
 216          $events = $sink->get_events();
 217          $event = array_pop($events); // Response submitted feedback event.
 218          $sink->close();
 219  
 220          // Validate event data. Feedback is anonymous.
 221          $this->assertInstanceOf('\mod_feedback\event\response_submitted', $event);
 222          $this->assertEquals($id, $event->objectid);
 223          $this->assertEquals($USER->id, $event->userid);
 224          $this->assertEquals($USER->id, $event->relateduserid);
 225          $this->assertEquals('feedback_completed', $event->objecttable);
 226          $this->assertEquals(1, $event->anonymous);
 227          $this->assertEquals(FEEDBACK_ANONYMOUS_YES, $event->other['anonymous']);
 228          $this->setUser($this->eventuser);
 229          $this->assertFalse($event->can_view());
 230          $this->assertDebuggingCalled();
 231          $this->setAdminUser();
 232          $this->assertTrue($event->can_view());
 233          $this->assertDebuggingCalled();
 234  
 235          // Create a temporary response, with anonymous set to no.
 236          $response = new \stdClass();
 237          $response->feedback = $this->eventcm->instance;
 238          $response->userid = $this->eventuser->id;
 239          $response->anonymous_response = FEEDBACK_ANONYMOUS_NO;
 240          $completedid = $DB->insert_record('feedback_completedtmp', $response);
 241          $completed = $DB->get_record('feedback_completedtmp', array('id' => $completedid), '*', MUST_EXIST);
 242          $value = new \stdClass();
 243          $value->course_id = $this->eventcourse->id;
 244          $value->item = $this->eventfeedbackitem->id;
 245          $value->completed = $completedid;
 246          $value->value = 25; // User response value.
 247          $DB->insert_record('feedback_valuetmp', $value);
 248  
 249          // Save the feedback.
 250          $sink = $this->redirectEvents();
 251          feedback_save_tmp_values($completed, false);
 252          $events = $sink->get_events();
 253          $event = array_pop($events); // Response submitted feedback event.
 254          $sink->close();
 255  
 256          // Test can_view().
 257          $this->assertTrue($event->can_view());
 258          $this->assertDebuggingCalled();
 259          $this->setAdminUser();
 260          $this->assertTrue($event->can_view());
 261          $this->assertDebuggingCalled();
 262          $this->assertEventContextNotUsed($event);
 263      }
 264  
 265      /**
 266       * Tests for event validations related to feedback response submission.
 267       */
 268      public function test_response_submitted_event_exceptions() {
 269  
 270          $this->resetAfterTest();
 271  
 272          $context = \context_module::instance($this->eventcm->id);
 273  
 274          // Test not setting instanceid.
 275          try {
 276              \mod_feedback\event\response_submitted::create(array(
 277                  'context'  => $context,
 278                  'objectid' => $this->eventfeedbackcompleted->id,
 279                  'relateduserid' => 2,
 280                  'anonymous' => 0,
 281                  'other'    => array('cmid' => $this->eventcm->id, 'anonymous' => 2)
 282              ));
 283              $this->fail("Event validation should not allow \\mod_feedback\\event\\response_deleted to be triggered without
 284                      other['instanceid']");
 285          } catch (\coding_exception $e) {
 286              $this->assertStringContainsString("The 'instanceid' value must be set in other.", $e->getMessage());
 287          }
 288  
 289          // Test not setting cmid.
 290          try {
 291              \mod_feedback\event\response_submitted::create(array(
 292                  'context'  => $context,
 293                  'objectid' => $this->eventfeedbackcompleted->id,
 294                  'relateduserid' => 2,
 295                  'anonymous' => 0,
 296                  'other'    => array('instanceid' => $this->eventfeedback->id, 'anonymous' => 2)
 297              ));
 298              $this->fail("Event validation should not allow \\mod_feedback\\event\\response_deleted to be triggered without
 299                      other['cmid']");
 300          } catch (\coding_exception $e) {
 301              $this->assertStringContainsString("The 'cmid' value must be set in other.", $e->getMessage());
 302          }
 303  
 304          // Test not setting anonymous.
 305          try {
 306              \mod_feedback\event\response_submitted::create(array(
 307                   'context'  => $context,
 308                   'objectid' => $this->eventfeedbackcompleted->id,
 309                   'relateduserid' => 2,
 310                   'other'    => array('cmid' => $this->eventcm->id, 'instanceid' => $this->eventfeedback->id)
 311              ));
 312              $this->fail("Event validation should not allow \\mod_feedback\\event\\response_deleted to be triggered without
 313                      other['anonymous']");
 314          } catch (\coding_exception $e) {
 315              $this->assertStringContainsString("The 'anonymous' value must be set in other.", $e->getMessage());
 316          }
 317      }
 318  
 319      /**
 320       * Test that event observer is executed on course deletion and the templates are removed.
 321       */
 322      public function test_delete_course() {
 323          global $DB;
 324          $this->resetAfterTest();
 325          feedback_save_as_template($this->eventfeedback, 'my template', 0);
 326          $courseid = $this->eventcourse->id;
 327          $this->assertNotEmpty($DB->get_records('feedback_template', array('course' => $courseid)));
 328          delete_course($this->eventcourse, false);
 329          $this->assertEmpty($DB->get_records('feedback_template', array('course' => $courseid)));
 330      }
 331  }