See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 402] [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 namespace core_courseformat\external; 18 19 defined('MOODLE_INTERNAL') || die(); 20 21 global $CFG; 22 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 23 24 use external_api; 25 26 /** 27 * Tests for the get_state class. 28 * 29 * @package core_course 30 * @category test 31 * @copyright 2021 Sara Arjona (sara@moodle.com) 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 * @coversDefaultClass \core_courseformat\external\get_state 34 */ 35 class get_state_test extends \externallib_advanced_testcase { 36 37 /** @var array Sections in the testing course. */ 38 private $sections; 39 40 /** @var array Activities in the testing course. */ 41 private $activities; 42 43 /** 44 * Setup to ensure that fixtures are loaded. 45 */ 46 public static function setupBeforeClass(): void { 47 global $CFG; 48 49 require_once($CFG->dirroot . '/course/lib.php'); 50 require_once($CFG->dirroot . '/course/format/tests/fixtures/format_theunittest.php'); 51 require_once($CFG->dirroot . '/course/format/tests/fixtures/format_theunittest_output_course_format_state.php'); 52 } 53 54 /** 55 * Setup testcase. 56 */ 57 public function setUp(): void { 58 $this->resetAfterTest(); 59 60 $this->sections = []; 61 $this->activities = []; 62 } 63 64 /** 65 * Test tearDown. 66 */ 67 public function tearDown(): void { 68 unset($this->sections); 69 unset($this->activities); 70 } 71 72 /** 73 * Test the behaviour of get_state::execute(). 74 * 75 * @dataProvider get_state_provider 76 * @covers ::execute 77 * 78 * @param string $role The role of the user that will execute the method. 79 * @param string $format The course format of the course where the method will be executed. 80 * @param string|null $expectedexception If this call will raise an exception, this is its name. 81 */ 82 public function test_get_state(string $role, string $format = 'topics', ?string $expectedexception = null): void { 83 $this->resetAfterTest(); 84 85 // Create a course. 86 $numsections = 6; 87 $visiblesections = $numsections + 1; // Include topic 0. 88 $course = $this->getDataGenerator()->create_course(['numsections' => $numsections, 'format' => $format]); 89 $hiddensections = [4, 6]; 90 foreach ($hiddensections as $section) { 91 set_section_visible($course->id, $section, 0); 92 } 93 94 // Create and enrol user. 95 $isadmin = ($role == 'admin'); 96 $canedit = $isadmin || ($role == 'editingteacher'); 97 if ($isadmin) { 98 $this->setAdminUser(); 99 } else { 100 if (!$canedit) { 101 // User won't see the hidden sections. Remove them from the total. 102 $visiblesections = $visiblesections - count($hiddensections); 103 } 104 $user = $this->getDataGenerator()->create_user(); 105 if ($role != 'unenroled') { 106 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role); 107 } 108 $this->setUser($user); 109 } 110 111 // Add some activities to the course. 112 $this->create_activity($course->id, 'page', 1, true, $canedit); 113 $this->create_activity($course->id, 'forum', 1, true, $canedit); 114 $this->create_activity($course->id, 'book', 1, false, $canedit); 115 $this->create_activity($course->id, 'assign', 2, false, $canedit); 116 $this->create_activity($course->id, 'glossary', 4, true, $canedit); 117 $this->create_activity($course->id, 'label', 5, false, $canedit); 118 $this->create_activity($course->id, 'feedback', 5, true, $canedit); 119 120 if ($expectedexception) { 121 $this->expectException($expectedexception); 122 } 123 124 // Get course state. 125 $result = get_state::execute($course->id); 126 $result = external_api::clean_returnvalue(get_state::execute_returns(), $result); 127 $result = json_decode($result); 128 if ($format == 'theunittest') { 129 // These course format's hasn't the renderer file, so a debugging message will be displayed. 130 $this->assertDebuggingCalled(); 131 } 132 133 // Check course information. 134 $this->assertEquals($numsections, $result->course->numsections); 135 $this->assertCount($visiblesections, $result->section); 136 $this->assertCount(count($this->activities), $result->cm); 137 $this->assertCount(count($result->course->sectionlist), $result->section); 138 if ($format == 'theunittest') { 139 $this->assertTrue(property_exists($result->course, 'newfancyelement')); 140 } else { 141 $this->assertFalse(property_exists($result->course, 'newfancyelement')); 142 } 143 144 // Check sections information. 145 foreach ($result->section as $section) { 146 if (in_array($section->number, $hiddensections)) { 147 $this->assertFalse($section->visible); 148 } else { 149 $this->assertTrue($section->visible); 150 } 151 // Check section is defined in course->sectionlist. 152 $this->assertContains($section->id, $result->course->sectionlist); 153 // Check course modules list for this section is the expected. 154 if (array_key_exists($section->number, $this->sections)) { 155 $this->assertEquals($this->sections[$section->number], $section->cmlist); 156 } 157 } 158 // Check course modules information. 159 foreach ($result->cm as $cm) { 160 $this->assertEquals($this->activities[$cm->id]->name, $cm->name); 161 $this->assertEquals((bool) $this->activities[$cm->id]->visible, $cm->visible); 162 } 163 } 164 165 /** 166 * Data provider for test_get_state(). 167 * 168 * @return array 169 */ 170 public function get_state_provider(): array { 171 return [ 172 // ROLES. Testing behaviour depending on the user role calling the method. 173 'Admin user should work' => [ 174 'role' => 'admin', 175 ], 176 'Editing teacher should work' => [ 177 'role' => 'editingteacher', 178 ], 179 'Student should work' => [ 180 'role' => 'student', 181 ], 182 'Unenroled user should raise an exception' => [ 183 'role' => 'unenroled', 184 'format' => 'topics', 185 'expectedexception' => 'moodle_exception', 186 ], 187 188 // COURSEFORMAT. Test behaviour depending on course formats. 189 'Single activity format should work (admin)' => [ 190 'role' => 'admin', 191 'format' => 'singleactivity', 192 ], 193 'Social format should work (admin)' => [ 194 'role' => 'admin', 195 'format' => 'social', 196 ], 197 'Weeks format should work (admin)' => [ 198 'role' => 'admin', 199 'format' => 'weeks', 200 ], 201 'The unit tests format should work (admin)' => [ 202 'role' => 'admin', 203 'format' => 'theunittest', 204 ], 205 'Single activity format should work (student)' => [ 206 'role' => 'student', 207 'format' => 'singleactivity', 208 ], 209 'Social format should work (student)' => [ 210 'role' => 'student', 211 'format' => 'social', 212 ], 213 'Weeks format should work (student)' => [ 214 'role' => 'student', 215 'format' => 'weeks', 216 ], 217 'The unit tests format should work (student)' => [ 218 'role' => 'student', 219 'format' => 'theunittest', 220 ], 221 'Single activity format should raise an exception (unenroled)' => [ 222 'role' => 'unenroled', 223 'format' => 'singleactivity', 224 'expectedexception' => 'moodle_exception', 225 ], 226 'Social format should raise an exception (unenroled)' => [ 227 'role' => 'unenroled', 228 'format' => 'social', 229 'expectedexception' => 'moodle_exception', 230 ], 231 'Weeks format should raise an exception (unenroled)' => [ 232 'role' => 'unenroled', 233 'format' => 'weeks', 234 'expectedexception' => 'moodle_exception', 235 ], 236 'The unit tests format should raise an exception (unenroled)' => [ 237 'role' => 'unenroled', 238 'format' => 'theunittest', 239 'expectedexception' => 'moodle_exception', 240 ], 241 ]; 242 } 243 244 /** 245 * Helper method to create an activity into a section and add it to the $sections and $activities arrays. 246 * For non-admin users, only visible activities will be added to the activities and sections arrays. 247 * 248 * @param int $courseid Course identifier where the activity will be added. 249 * @param string $type Activity type ('forum', 'assign', ...). 250 * @param int $section Section number where the activity will be added. 251 * @param bool $visible Whether the activity will be visible or not. 252 * @param bool $canedit Whether the activity will be accessed later by a user with editing capabilities 253 */ 254 private function create_activity(int $courseid, string $type, int $section, bool $visible = true, bool $canedit = true): void { 255 $activity = $this->getDataGenerator()->create_module( 256 $type, 257 ['course' => $courseid], 258 ['section' => $section, 'visible' => $visible] 259 ); 260 261 list(, $activitycm) = get_course_and_cm_from_instance($activity->id, $type); 262 263 if ($visible || $canedit) { 264 $this->activities[$activitycm->id] = $activitycm; 265 $this->sections[$section][] = $activitycm->id; 266 } 267 } 268 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body