See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401]
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 * Data generators for acceptance testing. 19 * 20 * @package core 21 * @category test 22 * @copyright 2012 David MonllaĆ³ 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. 27 28 require_once (__DIR__ . '/../../behat/behat_base.php'); 29 30 use Behat\Gherkin\Node\TableNode as TableNode; 31 use Behat\Behat\Tester\Exception\PendingException as PendingException; 32 33 /** 34 * Class to set up quickly a Given environment. 35 * 36 * The entry point is the Behat steps: 37 * the following "entity types" exist: 38 * | test | data | 39 * 40 * Entity type will either look like "users" or "activities" for core entities, or 41 * "mod_forum > subscription" or "core_message > message" for entities belonging 42 * to components. 43 * 44 * Generally, you only need to specify properties relevant to your test, 45 * and everything else gets set to sensible defaults. 46 * 47 * The actual generation of entities is done by {@link behat_generator_base}. 48 * There is one subclass for each component, e.g. {@link behat_core_generator} 49 * or {@link behat_mod_quiz_generator}. To see the types of entity 50 * that can be created for each component, look at the arrays returned 51 * by the get_creatable_entities() method in each class. 52 * 53 * @package core 54 * @category test 55 * @copyright 2012 David MonllaĆ³ 56 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 57 */ 58 class behat_data_generators extends behat_base { 59 60 /** 61 * Convert legacy entity names to the new component-specific form. 62 * 63 * In the past, there was no support for plugins, and everything that 64 * could be created was handled by the core generator. Now, we can 65 * support plugins, and so some thing should probably be moved. 66 * 67 * For example, in the future we should probably add 68 * 'message contacts' => 'core_message > contact'] to 69 * this array, and move generation of message contact 70 * from core to core_message. 71 * 72 * @var array old entity type => new entity type. 73 */ 74 protected $movedentitytypes = [ 75 ]; 76 77 /** 78 * Creates the specified elements. 79 * 80 * See the class comment for an overview. 81 * 82 * @Given /^the following "(?P<element_string>(?:[^"]|\\")*)" exist:$/ 83 * 84 * @param string $entitytype The name of the type entity to add 85 * @param TableNode $data 86 */ 87 public function the_following_entities_exist($entitytype, TableNode $data) { 88 if (isset($this->movedentitytypes[$entitytype])) { 89 $entitytype = $this->movedentitytypes[$entitytype]; 90 } 91 list($component, $entity) = $this->parse_entity_type($entitytype); 92 $this->get_instance_for_component($component)->generate_items($entity, $data); 93 } 94 95 /** 96 * Create multiple entities of one entity type. 97 * 98 * @Given :count :entitytype exist with the following data: 99 * 100 * @param string $entitytype The name of the type entity to add 101 * @param int $count 102 * @param TableNode $data 103 */ 104 public function the_following_repeated_entities_exist(string $entitytype, int $count, TableNode $data): void { 105 $rows = $data->getRowsHash(); 106 107 $tabledata = [array_keys($rows)]; 108 for ($current = 1; $current < $count + 1; $current++) { 109 $rowdata = []; 110 foreach ($rows as $fieldname => $fieldtemplate) { 111 $rowdata[$fieldname] = str_replace('[count]', $current, $fieldtemplate); 112 } 113 $tabledata[] = $rowdata; 114 } 115 116 if (isset($this->movedentitytypes[$entitytype])) { 117 $entitytype = $this->movedentitytypes[$entitytype]; 118 } 119 list($component, $entity) = $this->parse_entity_type($entitytype); 120 $this->get_instance_for_component($component)->generate_items($entity, new TableNode($tabledata), false); 121 } 122 123 /** 124 * Creates the specified (singular) element. 125 * 126 * See the class comment for an overview. 127 * 128 * @Given the following :entitytype exists: 129 * 130 * @param string $entitytype The name of the type entity to add 131 * @param TableNode $data 132 */ 133 public function the_following_entity_exists($entitytype, TableNode $data) { 134 if (isset($this->movedentitytypes[$entitytype])) { 135 $entitytype = $this->movedentitytypes[$entitytype]; 136 } 137 list($component, $entity) = $this->parse_entity_type($entitytype); 138 $this->get_instance_for_component($component)->generate_items($entity, $data, true); 139 } 140 141 /** 142 * Parse a full entity type like 'users' or 'mod_forum > subscription'. 143 * 144 * E.g. parsing 'course' gives ['core', 'course'] and 145 * parsing 'core_message > message' gives ['core_message', 'message']. 146 * 147 * @param string $entitytype the entity type 148 * @return string[] with two elements, component and entity type. 149 */ 150 protected function parse_entity_type(string $entitytype): array { 151 $dividercount = substr_count($entitytype, ' > '); 152 if ($dividercount === 0) { 153 return ['core', $entitytype]; 154 } else if ($dividercount === 1) { 155 list($component, $type) = explode(' > ', $entitytype); 156 if ($component === 'core') { 157 throw new coding_exception('Do not specify the component "core > ..." for entity types.'); 158 } 159 return [$component, $type]; 160 } else { 161 throw new coding_exception('The entity type must be in the form ' . 162 '"{entity-type}" for core entities, or "{component} > {entity-type}" ' . 163 'for entities belonging to other components. ' . 164 'For example "users" or "mod_forum > subscriptions".'); 165 } 166 } 167 168 /** 169 * Get an instance of the appropriate subclass of this class for a given component. 170 * 171 * @param string $component The name of the component to generate entities for. 172 * @return behat_generator_base the subclass of this class for the requested component. 173 */ 174 protected function get_instance_for_component(string $component): behat_generator_base { 175 global $CFG; 176 177 // Ensure the generator class is loaded. 178 require_once($CFG->libdir . '/behat/classes/behat_generator_base.php'); 179 if ($component === 'core') { 180 $lib = $CFG->libdir . '/behat/classes/behat_core_generator.php'; 181 } else { 182 $dir = core_component::get_component_directory($component); 183 $lib = $dir . '/tests/generator/behat_' . $component . '_generator.php'; 184 if (!$dir || !is_readable($lib)) { 185 throw new coding_exception("Component {$component} does not support " . 186 "behat generators yet. Missing {$lib}."); 187 } 188 } 189 require_once($lib); 190 191 // Create an instance. 192 $componentclass = "behat_{$component}_generator"; 193 if (!class_exists($componentclass)) { 194 throw new PendingException($component . 195 ' does not yet support the Behat data generator mechanism. Class ' . 196 $componentclass . ' not found in file ' . $lib . '.'); 197 } 198 $instance = new $componentclass($component); 199 return $instance; 200 } 201 202 /** 203 * Get all entities that can be created in all components using the_following_entities_exist() 204 * 205 * @return array 206 * @throws coding_exception 207 */ 208 public function get_all_entities(): array { 209 global $CFG; 210 // Ensure the generator class is loaded. 211 require_once($CFG->libdir . '/behat/classes/behat_generator_base.php'); 212 $componenttypes = core_component::get_component_list(); 213 $coregenerator = $this->get_instance_for_component('core'); 214 $pluginswithentities = ['core' => array_keys($coregenerator->get_available_generators())]; 215 foreach ($componenttypes as $components) { 216 foreach ($components as $component => $componentdir) { 217 try { 218 $plugingenerator = $this->get_instance_for_component($component); 219 $entities = array_keys($plugingenerator->get_available_generators()); 220 if (!empty($entities)) { 221 $pluginswithentities[$component] = $entities; 222 } 223 } catch (Exception $e) { 224 // The component has no generator, skip it. 225 continue; 226 } 227 } 228 } 229 return $pluginswithentities; 230 } 231 232 /** 233 * Get the required fields for a specific creatable entity. 234 * 235 * @param string $entitytype 236 * @return mixed 237 * @throws coding_exception 238 */ 239 public function get_entity(string $entitytype): array { 240 [$component, $entity] = $this->parse_entity_type($entitytype); 241 $generator = $this->get_instance_for_component($component); 242 $entities = $generator->get_available_generators(); 243 if (!array_key_exists($entity, $entities)) { 244 throw new coding_exception('No generator for ' . $entity . ' in component ' . $component); 245 } 246 return $entities[$entity]; 247 } 248 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body