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 use stdClass; 20 use moodle_exception; 21 22 defined('MOODLE_INTERNAL') || die(); 23 24 global $CFG; 25 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 26 27 /** 28 * Tests for the update_course class. 29 * 30 * @package core_course 31 * @category test 32 * @copyright 2021 Sara Arjona (sara@moodle.com) 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 * @coversDefaultClass \core_courseformat\external\update_course 35 */ 36 class update_course_test extends \externallib_advanced_testcase { 37 38 /** 39 * Setup to ensure that fixtures are loaded. 40 */ 41 public static function setupBeforeClass(): void { 42 global $CFG; 43 44 require_once($CFG->dirroot . '/course/format/tests/fixtures/format_theunittest.php'); 45 require_once($CFG->dirroot . '/course/format/tests/fixtures/format_theunittest_output_course_format_state.php'); 46 require_once($CFG->dirroot . '/course/format/tests/fixtures/format_theunittest_stateactions.php'); 47 } 48 49 /** 50 * Test the webservice can execute a core state action (cm_state). 51 * 52 * @dataProvider execute_course_state_provider 53 * @covers ::execute 54 * 55 * @param string $format the course format 56 * @param string $action the state action name 57 * @param array $expected the expected results 58 * @param bool $expectexception if an exception should happen. 59 * @param bool $assertdebug if an debug message should happen. 60 */ 61 public function test_execute_course_state( 62 string $format, 63 string $action, 64 array $expected, 65 bool $expectexception, 66 bool $assertdebug 67 ) { 68 69 $this->resetAfterTest(); 70 71 // Create a course with two activities. 72 $course = $this->getDataGenerator()->create_course(['format' => $format]); 73 $activity = $this->getDataGenerator()->create_module('book', ['course' => $course->id]); 74 75 $this->setAdminUser(); 76 77 // Expect exception. 78 if ($expectexception) { 79 $this->expectException(moodle_exception::class); 80 } 81 82 // Execute course action. 83 $results = json_decode(update_course::execute($action, $course->id, [$activity->cmid])); 84 85 if ($assertdebug) { 86 // Some course formats hasn't the renderer file, so a debugging message will be displayed. 87 $this->assertDebuggingCalled(); 88 } 89 90 // Check result. 91 $this->assertCount($expected['count'], $results); 92 93 $update = $this->find_update($results, $expected['action'], 'cm', $activity->cmid); 94 $this->assertNotEmpty($update); 95 if ($expected['visible'] === null) { 96 $this->assertObjectNotHasAttribute('visible', $update->fields); 97 } else { 98 $this->assertEquals($expected['visible'], $update->fields->visible); 99 } 100 } 101 102 /** 103 * Data provider for test_execute_course_state 104 * 105 * @return array of testing scenarios 106 */ 107 public function execute_course_state_provider(): array { 108 return [ 109 'Execute a core state action (cm_state)' => [ 110 'format' => 'topics', 111 'action' => 'cm_state', 112 'expected' => [ 113 'count' => 2, 114 'action' => 'put', 115 'visible' => 1, 116 ], 117 'expectexception' => false, 118 'assertdebug' => false, 119 ], 120 'Formats can override core state actions' => [ 121 'format' => 'theunittest', 122 'action' => 'cm_state', 123 'expected' => [ 124 'count' => 1, 125 'action' => 'create', 126 'visible' => 1, 127 ], 128 'expectexception' => false, 129 'assertdebug' => true, 130 ], 131 'Formats can create new state actions' => [ 132 'format' => 'theunittest', 133 'action' => 'format_do_something', 134 'expected' => [ 135 'count' => 1, 136 'action' => 'remove', 137 'visible' => null, 138 ], 139 'expectexception' => false, 140 'assertdebug' => true, 141 ], 142 'Innexisting state action' => [ 143 'format' => 'topics', 144 'action' => 'Wrong_State_Action_Name', 145 'expected' => [], 146 'expectexception' => true, 147 'assertdebug' => false, 148 ], 149 ]; 150 } 151 152 /** 153 * Helper methods to find a specific update in the updadelist. 154 * 155 * @param array $updatelist the update list 156 * @param string $action the action to find 157 * @param string $name the element name to find 158 * @param int $identifier the element id value 159 * @return stdClass|null the object found, if any. 160 */ 161 private function find_update( 162 array $updatelist, 163 string $action, 164 string $name, 165 int $identifier 166 ): ?stdClass { 167 foreach ($updatelist as $update) { 168 if ($update->action != $action || $update->name != $name) { 169 continue; 170 } 171 if (!isset($update->fields->id)) { 172 continue; 173 } 174 if ($update->fields->id == $identifier) { 175 return $update; 176 } 177 } 178 return null; 179 } 180 181 /** 182 * Test a wrong course id. 183 * 184 * @covers ::execute 185 * 186 */ 187 public function test_execute_wrong_courseid() { 188 189 $this->resetAfterTest(); 190 191 // Create a course with two activities. 192 $course = $this->getDataGenerator()->create_course(['format' => 'topics']); 193 $activity = $this->getDataGenerator()->create_module('book', ['course' => $course->id]); 194 195 $this->setAdminUser(); 196 197 // Expect exception. 198 $this->expectException(moodle_exception::class); 199 200 // Execute course action. 201 $results = json_decode(update_course::execute('cm_state', $course->id + 1, [$activity->cmid])); 202 } 203 204 /** 205 * Test target params are passed to the state actions. 206 * 207 * @covers ::execute 208 */ 209 public function test_execute_target_params() { 210 211 $this->resetAfterTest(); 212 213 // Create a course with two activities. 214 $course = $this->getDataGenerator()->create_course(['format' => 'theunittest', 'numsections' => 2]); 215 $activity = $this->getDataGenerator()->create_module('book', ['course' => $course->id]); 216 217 $modinfo = get_fast_modinfo($course); 218 $section = $modinfo->get_section_info(1); 219 220 $this->setAdminUser(); 221 222 // Execute action with targetsectionid. 223 $results = json_decode(update_course::execute('targetsection_test', $course->id, [], $section->id)); 224 $this->assertDebuggingCalled(); 225 $this->assertCount(1, $results); 226 $update = $this->find_update($results, 'put', 'section', $section->id); 227 $this->assertNotEmpty($update); 228 229 // Execute action with targetcmid. 230 $results = json_decode(update_course::execute('targetcm_test', $course->id, [], null, $activity->cmid)); 231 $this->assertDebuggingCalled(); 232 $this->assertCount(1, $results); 233 $update = $this->find_update($results, 'put', 'cm', $activity->cmid); 234 $this->assertNotEmpty($update); 235 } 236 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body