BehatConfigManager.php 7.78 KB
Newer Older
Son Nguyen's avatar
Son Nguyen committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
/**
 * @package    mahara
 * @subpackage test/behat
 * @author     Son Nguyen, Catalyst IT Ltd
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
 * @copyright  portions from Moodle Behat, 2013 David Monllaó
 *
 */


/**
 * Utils to set Behat config
 *
 */

defined('INTERNAL') || die();

require_once(dirname(__DIR__) . '/lib.php');
Son Nguyen's avatar
Son Nguyen committed
21
require_once(__DIR__ . '/util.php');
Son Nguyen's avatar
Son Nguyen committed
22
23
24
25
26
27
28
29
30
31
32
33
34
35
require_once(dirname(dirname(dirname(__DIR__))) . '/classes/TestsFinder.php');

/**
 * Behat configuration manager
 *
 * Creates/updates Behat config files getting tests
 * and steps from Mahara codebase
 *
 */
class BehatConfigManager {

    /**
     * Updates a config file
     *
Son Nguyen's avatar
Son Nguyen committed
36
     * Define test suites for mahara core and plugins
Son Nguyen's avatar
Son Nguyen committed
37
     *
Son Nguyen's avatar
Son Nguyen committed
38
39
40
41
42
43
44
     * Default test suite is
     *  - core_features
     *
     * Each test suite should have
     *  - paths of feature files
     *  - contexts
     *  - filters (for plugin test suite, use tags: pluginname)
Son Nguyen's avatar
Son Nguyen committed
45
46
47
     *
     * @return void
     */
Son Nguyen's avatar
Son Nguyen committed
48
    public static function update_config_file() {
Son Nguyen's avatar
Son Nguyen committed
49
50
        global $CFG;

Son Nguyen's avatar
Son Nguyen committed
51
        $configfilepath = BehatTestingUtil::get_behat_config_path();
Son Nguyen's avatar
Son Nguyen committed
52

Son Nguyen's avatar
Son Nguyen committed
53
54
        // Get core_features test suite
        $suites = array();
Son Nguyen's avatar
Son Nguyen committed
55

Son Nguyen's avatar
Son Nguyen committed
56
        $core_paths = array(BehatTestingUtil::get_mahararoot() . self::get_behat_tests_path(). DIRECTORY_SEPARATOR . 'features');
Son Nguyen's avatar
Son Nguyen committed
57
58
59

        // Optionally include features from additional directories.
        if (!empty($CFG->behat_additionalfeatures)) {
Son Nguyen's avatar
Son Nguyen committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
            $core_paths = array_merge($core_paths, array_map("realpath", $CFG->behat_additionalfeatures));
        }
        $core_contexts = array(
            'BehatMaharaCoreContext',
            'BehatHooks',
            'BehatGeneral',
            'BehatNavigation',
            'BehatView',
            'BehatDataGenerators',
            'BehatAccount',
            'BehatAdmin',
            'BehatForms',
        );
        $core_filters = array(
            'tags' => '@core'
        );
        $suites['core_features'] = array(
            'paths'    => $core_paths,
            'contexts' => $core_contexts,
            'filters'  => $core_filters,
        );
Son Nguyen's avatar
Son Nguyen committed
81

Son Nguyen's avatar
Son Nguyen committed
82
83
84
85
86
87
88
89
90
91
92
        // Get test suite config for each plugin
        // Gets all the plugins with features and/or contexts.
        $plugins = TestsFinder::get_plugins_with_tests('features');
        if ($plugins) {
            foreach ($plugins as $pluginname => $path) {
                $path = self::clean_path($path) ;
                if (file_exists($path . self::get_behat_tests_path())) {
                    $suites[$pluginname] = array(
                        'paths'    => array($path),
                        'contexts' => array_merge($core_contexts, self::get_plugin_contexts($path)),
                    );
Son Nguyen's avatar
Son Nguyen committed
93
94
                }

Son Nguyen's avatar
Son Nguyen committed
95
96
            }
            $features = array_merge($features, array_values($featurespaths));
Son Nguyen's avatar
Son Nguyen committed
97
98
99
100
        }

        // Behat config file specifing the main context class,
        // the required Behat extensions and Mahara test wwwroot.
Son Nguyen's avatar
Son Nguyen committed
101
        $contents = self::get_config_file_contents($suites);
Son Nguyen's avatar
Son Nguyen committed
102
103
104

        // Stores the file.
        if (!file_put_contents($configfilepath, $contents)) {
Son Nguyen's avatar
Son Nguyen committed
105
            behat_error(BEHAT_MAHARA_EXITCODE_BADPERMISSIONS, 'File ' . $configfilepath . ' can not be created');
Son Nguyen's avatar
Son Nguyen committed
106
107
108
109
110
        }

    }

    /**
Son Nguyen's avatar
Son Nguyen committed
111
     * Gets the list contexts for a plugin
Son Nguyen's avatar
Son Nguyen committed
112
     *
Son Nguyen's avatar
Son Nguyen committed
113
     * @param $pluginpath
Son Nguyen's avatar
Son Nguyen committed
114
115
     * @return array
     */
Son Nguyen's avatar
Son Nguyen committed
116
    public static function get_plugin_contexts($pluginpath) {
Son Nguyen's avatar
Son Nguyen committed
117

Son Nguyen's avatar
Son Nguyen committed
118
        $plugincontexts = array();
Son Nguyen's avatar
Son Nguyen committed
119

Son Nguyen's avatar
Son Nguyen committed
120
121
122
123
124
        // All Behat*.php inside self::get_behat_tests_path() are added contexts.
        $regite = new RegexIterator(new DirectoryIterator($pluginpath . self::get_behat_tests_path()), '|^Behat.*\.php$|');
        foreach ($regite as $file) {
            $key = $file->getBasename('.php');
            $plugincontexts[] = $key;
Son Nguyen's avatar
Son Nguyen committed
125
126
        }

Son Nguyen's avatar
Son Nguyen committed
127
        return $plugincontexts;
Son Nguyen's avatar
Son Nguyen committed
128
129
130
    }

    /**
Son Nguyen's avatar
Son Nguyen committed
131
     * Generate the Behat config file
Son Nguyen's avatar
Son Nguyen committed
132
     *
Son Nguyen's avatar
Son Nguyen committed
133
     * @param array $suites
Son Nguyen's avatar
Son Nguyen committed
134
135
     * @return string
     */
Son Nguyen's avatar
Son Nguyen committed
136
    protected static function get_config_file_contents($suites) {
Son Nguyen's avatar
Son Nguyen committed
137
138
139
        global $CFG;

        // We require here when we are sure behat dependencies are available.
Son Nguyen's avatar
Son Nguyen committed
140
        require_once(TestingUtil::get_mahararoot() . '/external/vendor/autoload.php');
Son Nguyen's avatar
Son Nguyen committed
141
142
143

        // It is possible that it has no value as we don't require a full behat setup to list the step definitions.
        if (empty($CFG->behat_wwwroot)) {
Son Nguyen's avatar
Son Nguyen committed
144
            $CFG->behat_wwwroot = 'http://example.com';
Son Nguyen's avatar
Son Nguyen committed
145
146
        }

Son Nguyen's avatar
Son Nguyen committed
147
        $basedir = $CFG->docroot . 'testing/frameworks/behat';
Son Nguyen's avatar
Son Nguyen committed
148
149
        $config = array(
            'default' => array(
Son Nguyen's avatar
Son Nguyen committed
150
151
152
                'autoload' => array($basedir . DIRECTORY_SEPARATOR . 'classes'),
                'formatters' => array(
                    'progress' => true
Son Nguyen's avatar
Son Nguyen committed
153
154
                ),
                'extensions' => array(
Son Nguyen's avatar
Son Nguyen committed
155
                    'Behat\MinkExtension' => array(
Son Nguyen's avatar
Son Nguyen committed
156
                        'base_url' => $CFG->behat_wwwroot,
Son Nguyen's avatar
Son Nguyen committed
157
                        'files_path' => get_mahararoot_dir() . '/test/behat/upload_files',
Son Nguyen's avatar
Son Nguyen committed
158
159
160
161
162
163
164
                        'sessions' => array(
                            'default' => array(
                                'selenium2' => null
                            ),
                            'headless' => array(
                                'goutte' => null
                            ),
Son Nguyen's avatar
Son Nguyen committed
165
                        ),
Son Nguyen's avatar
Son Nguyen committed
166
                     ),
Son Nguyen's avatar
Son Nguyen committed
167
                ),
Son Nguyen's avatar
Son Nguyen committed
168
                'suites' => $suites
Son Nguyen's avatar
Son Nguyen committed
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
            )
        );

        // In case user defined overrides respect them over our default ones.
        if (!empty($CFG->behat_config)) {
            $config = self::merge_config($config, $CFG->behat_config);
        }

        return Symfony\Component\Yaml\Yaml::dump($config, 10, 2);
    }

    /**
     * Overrides default config with local config values
     *
     * array_merge does not merge completely the array's values
     *
     * @param mixed $config The node of the default config
     * @param mixed $localconfig The node of the local config
     * @return mixed The merge result
     */
    protected static function merge_config($config, $localconfig) {

        if (!is_array($config) && !is_array($localconfig)) {
            return $localconfig;
        }

        // Local overrides also deeper default values.
        if (is_array($config) && !is_array($localconfig)) {
            return $localconfig;
        }

        foreach ($localconfig as $key => $value) {

            // If defaults are not as deep as local values let locals override.
            if (!is_array($config)) {
                unset($config);
            }

            // Add the param if it doesn't exists or merge branches.
            if (empty($config[$key])) {
                $config[$key] = $value;
Son Nguyen's avatar
Son Nguyen committed
210
211
            }
            else {
Son Nguyen's avatar
Son Nguyen committed
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
                $config[$key] = self::merge_config($config[$key], $localconfig[$key]);
            }
        }

        return $config;
    }

    /**
     * Cleans the path returned by get_plugins_with_tests() to standarize it
     *
     * @see TestsFinder::get_all_directories_with_tests() it returns the path including /tests/
     * @param string $path
     * @return string The string without the last /tests part
     */
    protected final static function clean_path($path) {

        $path = rtrim($path, DIRECTORY_SEPARATOR);

        $parttoremove = DIRECTORY_SEPARATOR . 'tests';

        $substr = substr($path, strlen($path) - strlen($parttoremove));
        if ($substr == $parttoremove) {
            $path = substr($path, 0, strlen($path) - strlen($parttoremove));
        }

        return rtrim($path, DIRECTORY_SEPARATOR);
    }

    /**
     * The relative path where plugins stores their behat tests
     *
     * @return string
     */
    protected final static function get_behat_tests_path() {
Son Nguyen's avatar
Son Nguyen committed
246
        return DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'behat';
Son Nguyen's avatar
Son Nguyen committed
247
248
249
    }

}