MDL-69068 behat: New step to support singular generators
[moodle.git] / lib / tests / behat / behat_data_generators.php
CommitLineData
f0200d14 1<?php
f0200d14
DM
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
28require_once(__DIR__ . '/../../behat/behat_base.php');
f0200d14
DM
29
30use Behat\Gherkin\Node\TableNode as TableNode;
134494e0 31use Behat\Behat\Tester\Exception\PendingException as PendingException;
f0200d14
DM
32
33/**
34 * Class to set up quickly a Given environment.
35 *
285c7036
TH
36 * The entry point is the Behat steps:
37 * the following "entity types" exist:
38 * | test | data |
f0200d14 39 *
285c7036
TH
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.
f0200d14 52 *
f0200d14
DM
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 */
58class behat_data_generators extends behat_base {
59
46ac40cd 60 /**
285c7036 61 * Convert legacy entity names to the new component-specific form.
eb3884e4 62 *
285c7036
TH
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.
4d0ac716 66 *
285c7036
TH
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.
81cd8572 71 *
285c7036 72 * @var array old entity type => new entity type.
81cd8572 73 */
285c7036
TH
74 protected $movedentitytypes = [
75 ];
81cd8572 76
d2eca4cd 77 /**
b49cb92e 78 * Creates the specified elements.
72ddc05f 79 *
285c7036 80 * See the class comment for an overview.
72ddc05f 81 *
285c7036 82 * @Given /^the following "(?P<element_string>(?:[^"]|\\")*)" exist:$/
702851c0 83 *
285c7036
TH
84 * @param string $entitytype The name of the type entity to add
85 * @param TableNode $data
702851c0 86 */
285c7036
TH
87 public function the_following_entities_exist($entitytype, TableNode $data) {
88 if (isset($this->movedentitytypes[$entitytype])) {
89 $entitytype = $this->movedentitytypes[$entitytype];
702851c0 90 }
285c7036
TH
91 list($component, $entity) = $this->parse_entity_type($entitytype);
92 $this->get_instance_for_component($component)->generate_items($entity, $data);
702851c0
DM
93 }
94
b49cb92e
AN
95 /**
96 * Creates the specified element.
97 *
98 * See the class comment for an overview.
99 *
100 * @Given the following :entitytype exists:
101 *
102 * @param string $entitytype The name of the type entity to add
103 * @param TableNode $data
104 */
105 public function the_following_entity_exists($entitytype, TableNode $data) {
106 if (isset($this->movedentitytypes[$entitytype])) {
107 $entitytype = $this->movedentitytypes[$entitytype];
108 }
109 list($component, $entity) = $this->parse_entity_type($entitytype);
110 $this->get_instance_for_component($component)->generate_items($entity, $data, true);
111 }
112
9cc66e86 113 /**
285c7036 114 * Parse a full entity type like 'users' or 'mod_forum > subscription'.
9cc66e86 115 *
285c7036
TH
116 * E.g. parsing 'course' gives ['core', 'course'] and
117 * parsing 'core_message > message' gives ['core_message', 'message'].
0db16e08 118 *
285c7036
TH
119 * @param string $entitytype the entity type
120 * @return string[] with two elements, component and entity type.
0db16e08 121 */
285c7036
TH
122 protected function parse_entity_type(string $entitytype): array {
123 $dividercount = substr_count($entitytype, ' > ');
124 if ($dividercount === 0) {
125 return ['core', $entitytype];
126 } else if ($dividercount === 1) {
127 list($component, $type) = explode(' > ', $entitytype);
128 if ($component === 'core') {
129 throw new coding_exception('Do not specify the component "core > ..." for entity types.');
6e73157a 130 }
285c7036
TH
131 return [$component, $type];
132 } else {
133 throw new coding_exception('The entity type must be in the form ' .
134 '"{entity-type}" for core entities, or "{component} > {entity-type}" ' .
135 'for entities belonging to other components. ' .
136 'For example "users" or "mod_forum > subscriptions".');
6e73157a 137 }
173be485
AA
138 }
139
140 /**
285c7036 141 * Get an instance of the appropriate subclass of this class for a given component.
173be485 142 *
285c7036
TH
143 * @param string $component The name of the component to generate entities for.
144 * @return behat_generator_base the subclass of this class for the requested component.
173be485 145 */
285c7036
TH
146 protected function get_instance_for_component(string $component): behat_generator_base {
147 global $CFG;
f0e8f0a5 148
285c7036
TH
149 // Ensure the generator class is loaded.
150 require_once($CFG->libdir . '/behat/classes/behat_generator_base.php');
151 if ($component === 'core') {
152 $lib = $CFG->libdir . '/behat/classes/behat_core_generator.php';
153 } else {
154 $dir = core_component::get_component_directory($component);
155 $lib = $dir . '/tests/generator/behat_' . $component . '_generator.php';
156 if (!$dir || !is_readable($lib)) {
157 throw new coding_exception("Component {$component} does not support " .
158 "behat generators yet. Missing {$lib}.");
f0e8f0a5
AA
159 }
160 }
285c7036 161 require_once($lib);
f0e8f0a5 162
285c7036
TH
163 // Create an instance.
164 $componentclass = "behat_{$component}_generator";
165 if (!class_exists($componentclass)) {
166 throw new PendingException($component .
167 ' does not yet support the Behat data generator mechanism. Class ' .
168 $componentclass . ' not found in file ' . $lib . '.');
f0e8f0a5 169 }
285c7036
TH
170 $instance = new $componentclass($component);
171 return $instance;
a9e58c14 172 }
f0200d14 173}