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 namespace core_courseformat; 18 19 use stdClass; 20 21 /** 22 * Tests for the stateupdates class. 23 * 24 * @package core_courseformat 25 * @category test 26 * @copyright 2021 Sara Arjona (sara@moodle.com) 27 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 * @coversDefaultClass \core_courseformat\stateupdates 29 */ 30 class stateupdates_test extends \advanced_testcase { 31 32 /** 33 * Test for add_course_put. 34 * 35 * @dataProvider add_course_put_provider 36 * @covers ::add_course_put 37 * 38 * @param string $role the user role in the course 39 */ 40 public function test_add_course_put(string $role): void { 41 global $PAGE; 42 43 $this->resetAfterTest(); 44 45 $course = $this->getDataGenerator()->create_course(['format' => 'topics']); 46 47 // Create and enrol user using given role. 48 if ($role == 'admin') { 49 $this->setAdminUser(); 50 } else { 51 $user = $this->getDataGenerator()->create_user(); 52 if ($role != 'unenroled') { 53 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role); 54 } 55 $this->setUser($user); 56 } 57 58 // Initialise stateupdates. 59 $format = course_get_format($course); 60 $updates = new stateupdates($format); 61 62 // Get the expected export. 63 $renderer = $format->get_renderer($PAGE); 64 $stateclass = $format->get_output_classname("state\\course"); 65 $currentstate = new $stateclass($format); 66 $expected = $currentstate->export_for_template($renderer); 67 68 $updates->add_course_put(); 69 70 $updatelist = $updates->jsonSerialize(); 71 $this->assertCount(1, $updatelist); 72 73 $update = array_pop($updatelist); 74 $this->assertEquals('put', $update->action); 75 $this->assertEquals('course', $update->name); 76 $this->assertEquals($expected, $update->fields); 77 } 78 79 /** 80 * Data provider for test_add_course_put. 81 * 82 * @return array testing scenarios 83 */ 84 public function add_course_put_provider() { 85 return [ 86 'Admin role' => [ 87 'admin', 88 ], 89 'Teacher role' => [ 90 'editingteacher', 91 ], 92 'Student role' => [ 93 'student', 94 ], 95 ]; 96 } 97 98 /** 99 * Helper methods to find a specific update in the updadelist. 100 * 101 * @param array $updatelist the update list 102 * @param string $action the action to find 103 * @param string $name the element name to find 104 * @param int $identifier the element id value 105 * @return stdClass|null the object found, if any. 106 */ 107 private function find_update( 108 array $updatelist, 109 string $action, 110 string $name, 111 int $identifier 112 ): ?stdClass { 113 foreach ($updatelist as $update) { 114 if ($update->action != $action || $update->name != $name) { 115 continue; 116 } 117 if (!isset($update->fields->id)) { 118 continue; 119 } 120 if ($update->fields->id == $identifier) { 121 return $update; 122 } 123 } 124 return null; 125 } 126 127 /** 128 * Add track about a section state update. 129 * 130 * @dataProvider add_section_provider 131 * @covers ::add_section_create 132 * @covers ::add_section_remove 133 * @covers ::add_section_put 134 * 135 * @param string $action the action name 136 * @param string $role the user role name 137 * @param array $expected the expected results 138 */ 139 public function test_add_section(string $action, string $role, array $expected): void { 140 global $PAGE, $DB; 141 142 $this->resetAfterTest(); 143 144 $course = $this->getDataGenerator()->create_course(['numsections' => 2, 'format' => 'topics']); 145 146 // Set section 2 hidden. 147 set_section_visible($course->id, 2, 0); 148 149 // Create and enrol user using given role. 150 if ($role == 'admin') { 151 $this->setAdminUser(); 152 } else { 153 $user = $this->getDataGenerator()->create_user(); 154 if ($role != 'unenroled') { 155 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role); 156 } 157 $this->setUser($user); 158 } 159 160 // Initialise stateupdates. 161 $format = course_get_format($course); 162 $updates = new stateupdates($format); 163 164 $modinfo = $format->get_modinfo(); 165 166 // Get the expected export. 167 $renderer = $format->get_renderer($PAGE); 168 $stateclass = $format->get_output_classname("state\\section"); 169 170 // Execute method for both sections. 171 $method = "add_section_{$action}"; 172 $sections = $modinfo->get_section_info_all(); 173 foreach ($sections as $section) { 174 $updates->$method($section->id); 175 } 176 177 $updatelist = $updates->jsonSerialize(); 178 $this->assertCount(count($expected), $updatelist); 179 180 foreach ($expected as $sectionnum) { 181 $section = $sections[$sectionnum]; 182 $currentstate = new $stateclass($format, $section); 183 $expected = $currentstate->export_for_template($renderer); 184 185 $update = $this->find_update($updatelist, $action, 'section', $section->id); 186 $this->assertEquals($action, $update->action); 187 $this->assertEquals('section', $update->name); 188 // Delete does not provide all fields. 189 if ($action == 'remove') { 190 $this->assertEquals($section->id, $update->fields->id); 191 } else { 192 $this->assertEquals($expected, $update->fields); 193 } 194 } 195 } 196 197 /** 198 * Data provider for test_add_section. 199 * 200 * @return array testing scenarios 201 */ 202 public function add_section_provider(): array { 203 return array_merge( 204 $this->add_section_provider_helper('put'), 205 $this->add_section_provider_helper('create'), 206 $this->add_section_provider_helper('remove'), 207 ); 208 } 209 210 /** 211 * Helper for add_section_provider scenarios. 212 * 213 * @param string $action the action to perform 214 * @return array testing scenarios 215 */ 216 private function add_section_provider_helper(string $action): array { 217 // Delete does not depends on user permissions. 218 if ($action == 'remove') { 219 $studentsections = [0, 1, 2]; 220 } else { 221 $studentsections = [0, 1]; 222 } 223 224 return [ 225 "$action admin role" => [ 226 'action' => $action, 227 'role' => 'admin', 228 'expected' => [0, 1, 2], 229 ], 230 "$action teacher role" => [ 231 'action' => $action, 232 'role' => 'editingteacher', 233 'expected' => [0, 1, 2], 234 ], 235 "$action student role" => [ 236 'action' => $action, 237 'role' => 'student', 238 'expected' => $studentsections, 239 ], 240 ]; 241 } 242 243 244 /** 245 * Add track about a course module state update. 246 * 247 * @dataProvider add_cm_provider 248 * @covers ::add_cm_put 249 * @covers ::add_cm_create 250 * @covers ::add_cm_remove 251 * 252 * @param string $action the action name 253 * @param string $role the user role name 254 * @param array $expected the expected results 255 */ 256 public function test_add_cm(string $action, string $role, array $expected): void { 257 global $PAGE, $DB; 258 259 $this->resetAfterTest(); 260 261 $course = $this->getDataGenerator()->create_course(['numsections' => 2, 'format' => 'topics']); 262 263 // Set section 2 hidden. 264 set_section_visible($course->id, 2, 0); 265 266 // Create 2 activities on each section. 267 $activities = []; 268 $activities[] = $this->getDataGenerator()->create_module( 269 'book', 270 ['course' => $course->id], 271 ['section' => 1, 'visible' => true] 272 ); 273 $activities[] = $this->getDataGenerator()->create_module( 274 'book', 275 ['course' => $course->id], 276 ['section' => 1, 'visible' => false] 277 ); 278 $activities[] = $this->getDataGenerator()->create_module( 279 'book', 280 ['course' => $course->id], 281 ['section' => 2, 'visible' => true] 282 ); 283 $activities[] = $this->getDataGenerator()->create_module( 284 'book', 285 ['course' => $course->id], 286 ['section' => 2, 'visible' => false] 287 ); 288 289 // Create and enrol user using given role. 290 if ($role == 'admin') { 291 $this->setAdminUser(); 292 } else { 293 $user = $this->getDataGenerator()->create_user(); 294 if ($role != 'unenroled') { 295 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role); 296 } 297 $this->setUser($user); 298 } 299 300 // Initialise stateupdates. 301 $format = course_get_format($course); 302 $updates = new stateupdates($format); 303 304 $modinfo = $format->get_modinfo(); 305 306 // Get the expected export. 307 $renderer = $format->get_renderer($PAGE); 308 $stateclass = $format->get_output_classname("state\\cm"); 309 310 // Execute method for both sections. 311 $method = "add_cm_{$action}"; 312 313 foreach ($activities as $activity) { 314 $updates->$method($activity->cmid); 315 } 316 317 $updatelist = $updates->jsonSerialize(); 318 $this->assertCount(count($expected), $updatelist); 319 320 foreach ($expected as $cmnum) { 321 $activity = $activities[$cmnum]; 322 323 $cm = $modinfo->get_cm($activity->cmid); 324 $section = $modinfo->get_section_info($cm->sectionnum); 325 326 $currentstate = new $stateclass($format, $section, $cm); 327 $expected = $currentstate->export_for_template($renderer); 328 329 $update = $this->find_update($updatelist, $action, 'cm', $cm->id); 330 $this->assertEquals($action, $update->action); 331 $this->assertEquals('cm', $update->name); 332 // Delete does not provide all fields. 333 if ($action == 'remove') { 334 $this->assertEquals($cm->id, $update->fields->id); 335 } else { 336 $this->assertEquals($expected, $update->fields); 337 } 338 } 339 } 340 341 /** 342 * Data provider for test_add_cm. 343 * 344 * @return array testing scenarios 345 */ 346 public function add_cm_provider(): array { 347 return array_merge( 348 $this->add_cm_provider_helper('put'), 349 $this->add_cm_provider_helper('create'), 350 $this->add_cm_provider_helper('remove'), 351 ); 352 } 353 354 /** 355 * Helper for add_cm_provider scenarios. 356 * 357 * @param string $action the action to perform 358 * @return array testing scenarios 359 */ 360 private function add_cm_provider_helper(string $action): array { 361 // Delete does not depends on user permissions. 362 if ($action == 'remove') { 363 $studentcms = [0, 1, 2, 3]; 364 } else { 365 $studentcms = [0]; 366 } 367 368 return [ 369 "$action admin role" => [ 370 'action' => $action, 371 'role' => 'admin', 372 'expected' => [0, 1, 2, 3], 373 ], 374 "$action teacher role" => [ 375 'action' => $action, 376 'role' => 'editingteacher', 377 'expected' => [0, 1, 2, 3], 378 ], 379 "$action student role" => [ 380 'action' => $action, 381 'role' => 'student', 382 'expected' => $studentcms, 383 ], 384 ]; 385 } 386 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body