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 * Contains unit tests for core_completion/activity_custom_completion. 19 * 20 * @package mod_forum 21 * @copyright Simey Lameze <simey@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 declare(strict_types=1); 26 27 namespace mod_forum; 28 29 use advanced_testcase; 30 use cm_info; 31 use coding_exception; 32 use mod_forum\completion\custom_completion; 33 use moodle_exception; 34 35 defined('MOODLE_INTERNAL') || die(); 36 37 global $CFG; 38 require_once($CFG->libdir . '/completionlib.php'); 39 require_once($CFG->dirroot . '/mod/forum/tests/generator/lib.php'); 40 require_once($CFG->dirroot . '/mod/forum/tests/generator_trait.php'); 41 42 /** 43 * Class for unit testing mod_forum/activity_custom_completion. 44 * 45 * @package mod_forum 46 * @copyright Simey Lameze <simey@moodle.com> 47 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 48 */ 49 class custom_completion_test extends advanced_testcase { 50 51 use \mod_forum_tests_generator_trait; 52 53 /** 54 * Data provider for get_state(). 55 * 56 * @return array[] 57 */ 58 public function get_state_provider(): array { 59 return [ 60 'Undefined rule' => [ 61 'somenonexistentrule', 0, COMPLETION_TRACKING_NONE, 0, 0, 0, null, coding_exception::class 62 ], 63 'Completion discussions rule not available' => [ 64 'completiondiscussions', 0, COMPLETION_TRACKING_NONE, 0, 0, 0, null, moodle_exception::class 65 ], 66 'Completion discussions rule available, user has not created discussion' => [ 67 'completiondiscussions', 0, COMPLETION_TRACKING_AUTOMATIC, 5, 0, 0, COMPLETION_INCOMPLETE, null 68 ], 69 'Rule available, user has created discussions' => [ 70 'completiondiscussions', 5, COMPLETION_TRACKING_AUTOMATIC, 5, 0, 0, COMPLETION_COMPLETE, null 71 ], 72 'Completion replies rule not available' => [ 73 'completionreplies', 0, COMPLETION_TRACKING_NONE, 0, 0, 0, null, moodle_exception::class 74 ], 75 'Rule available, user has not replied' => [ 76 'completionreplies', 0, COMPLETION_TRACKING_AUTOMATIC, 0, 5, 0, COMPLETION_INCOMPLETE, null 77 ], 78 'Rule available, user has created replied' => [ 79 'completionreplies', 5, COMPLETION_TRACKING_AUTOMATIC, 0, 5, 0, COMPLETION_COMPLETE, null 80 ], 81 'Completion posts rule not available' => [ 82 'completionposts', 0, COMPLETION_TRACKING_NONE, 0, 0, 0, null, moodle_exception::class 83 ], 84 'Rule available, user has not posted' => [ 85 'completionposts', 0, COMPLETION_TRACKING_AUTOMATIC, 0, 0, 5, COMPLETION_INCOMPLETE, null 86 ], 87 'Rule available, user has posted' => [ 88 'completionposts', 5, COMPLETION_TRACKING_AUTOMATIC, 0, 0, 5, COMPLETION_COMPLETE, null 89 ], 90 ]; 91 } 92 93 /** 94 * Test for get_state(). 95 * 96 * @dataProvider get_state_provider 97 * @param string $rule The custom completion rule. 98 * @param int $rulecount Quantity of discussions, replies or posts to be created. 99 * @param int $available Whether this rule is available. 100 * @param int|null $discussions The number of discussions. 101 * @param int|null $replies The number of replies. 102 * @param int|null $posts The number of posts. 103 * @param int|null $status Expected status. 104 * @param string|null $exception Expected exception. 105 */ 106 public function test_get_state(string $rule, int $rulecount, int $available, ?int $discussions, ?int $replies, 107 ?int $posts, ?int $status, ?string $exception) { 108 109 if (!is_null($exception)) { 110 $this->expectException($exception); 111 } 112 113 $this->resetAfterTest(); 114 115 $course = $this->getDataGenerator()->create_course(['enablecompletion' => COMPLETION_ENABLED]); 116 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 117 118 $forumgenerator = $this->getDataGenerator()->get_plugin_generator('mod_forum'); 119 120 $params = [ 121 'course' => $course->id, 122 'completion' => $available, 123 'completiondiscussions' => $discussions, 124 'completionreplies' => $replies, 125 'completionposts' => $posts 126 ]; 127 $forum = $this->getDataGenerator()->create_module('forum', $params); 128 129 $cm = get_coursemodule_from_instance('forum', $forum->id); 130 131 if ($rulecount > 0) { 132 if ($rule == 'completiondiscussions') { 133 // Create x number of discussions. 134 for ($i = 0; $i < $rulecount; $i++) { 135 $forumgenerator->create_discussion((object) [ 136 'course' => $forum->course, 137 'userid' => $student->id, 138 'forum' => $forum->id, 139 ]); 140 } 141 } else if ($rule == 'completionreplies') { 142 [$discussion1, $post1] = $this->helper_post_to_forum($forum, $student); 143 for ($i = 0; $i < $rulecount; $i++) { 144 $this->helper_reply_to_post($post1, $student); 145 } 146 } else if ($rule == 'completionposts') { 147 for ($i = 0; $i < $rulecount; $i++) { 148 $this->helper_post_to_forum($forum, $student); 149 } 150 } 151 } 152 153 // Make sure we're using a cm_info object. 154 $cm = cm_info::create($cm); 155 156 $customcompletion = new custom_completion($cm, (int)$student->id); 157 $this->assertEquals($status, $customcompletion->get_state($rule)); 158 } 159 160 /** 161 * Test for get_defined_custom_rules(). 162 */ 163 public function test_get_defined_custom_rules() { 164 $rules = custom_completion::get_defined_custom_rules(); 165 $this->assertCount(3, $rules); 166 $this->assertEquals('completiondiscussions', reset($rules)); 167 } 168 169 /** 170 * Test for get_defined_custom_rule_descriptions(). 171 */ 172 public function test_get_custom_rule_descriptions() { 173 // Get defined custom rules. 174 $rules = custom_completion::get_defined_custom_rules(); 175 176 // Build a mock cm_info instance. 177 $mockcminfo = $this->getMockBuilder(cm_info::class) 178 ->disableOriginalConstructor() 179 ->onlyMethods(['__get']) 180 ->getMock(); 181 // Instantiate a custom_completion object using the mocked cm_info. 182 $customcompletion = new custom_completion($mockcminfo, 1); 183 184 // Get custom rule descriptions. 185 $ruledescriptions = $customcompletion->get_custom_rule_descriptions(); 186 187 // Confirm that defined rules and rule descriptions are consistent with each other. 188 $this->assertEquals(count($rules), count($ruledescriptions)); 189 foreach ($rules as $rule) { 190 $this->assertArrayHasKey($rule, $ruledescriptions); 191 } 192 } 193 194 /** 195 * Test for is_defined(). 196 */ 197 public function test_is_defined() { 198 // Build a mock cm_info instance. 199 $mockcminfo = $this->getMockBuilder(cm_info::class) 200 ->disableOriginalConstructor() 201 ->getMock(); 202 203 $customcompletion = new custom_completion($mockcminfo, 1); 204 205 // Rule is defined. 206 $this->assertTrue($customcompletion->is_defined('completiondiscussions')); 207 208 // Undefined rule. 209 $this->assertFalse($customcompletion->is_defined('somerandomrule')); 210 } 211 212 /** 213 * Data provider for test_get_available_custom_rules(). 214 * 215 * @return array[] 216 */ 217 public function get_available_custom_rules_provider(): array { 218 return [ 219 'Completion discussions available' => [ 220 COMPLETION_ENABLED, ['completiondiscussions'] 221 ], 222 'Completion discussions not available' => [ 223 COMPLETION_DISABLED, [] 224 ], 225 'Completion replies available' => [ 226 COMPLETION_ENABLED, ['completionreplies'] 227 ], 228 'Completion replies not available' => [ 229 COMPLETION_DISABLED, [] 230 ], 231 'Completion posts available' => [ 232 COMPLETION_ENABLED, ['completionposts'] 233 ], 234 'Completion posts not available' => [ 235 COMPLETION_DISABLED, [] 236 ], 237 ]; 238 } 239 240 /** 241 * Test for get_available_custom_rules(). 242 * 243 * @dataProvider get_available_custom_rules_provider 244 * @param int $status 245 * @param array $expected 246 */ 247 public function test_get_available_custom_rules(int $status, array $expected) { 248 $customdataval = [ 249 'customcompletionrules' => [] 250 ]; 251 if ($status == COMPLETION_ENABLED) { 252 $rule = $expected[0]; 253 $customdataval = [ 254 'customcompletionrules' => [$rule => $status] 255 ]; 256 } 257 258 // Build a mock cm_info instance. 259 $mockcminfo = $this->getMockBuilder(cm_info::class) 260 ->disableOriginalConstructor() 261 ->onlyMethods(['__get']) 262 ->getMock(); 263 264 // Mock the return of magic getter for the customdata attribute. 265 $mockcminfo->expects($this->any()) 266 ->method('__get') 267 ->with('customdata') 268 ->willReturn($customdataval); 269 270 $customcompletion = new custom_completion($mockcminfo, 1); 271 $this->assertEquals($expected, $customcompletion->get_available_custom_rules()); 272 } 273 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body