Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * Behat custom steps and configuration for mod_bigbluebuttonbn.
19
 *
20
 * @package   mod_bigbluebuttonbn
21
 * @category  test
22
 * @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
23
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
require_once(__DIR__ . '/../../../../lib/behat/behat_base.php');
27
 
28
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
29
use Behat\Gherkin\Node\TableNode;
30
use mod_bigbluebuttonbn\instance;
31
use mod_bigbluebuttonbn\local\config;
32
use mod_bigbluebuttonbn\test\subplugins_test_helper_trait;
33
use Moodle\BehatExtension\Exception\SkippedException;
34
require_once(__DIR__ . '../../../classes/test/subplugins_test_helper_trait.php');
35
/**
36
 * Behat custom steps and configuration for mod_bigbluebuttonbn.
37
 *
38
 * @package   mod_bigbluebuttonbn
39
 * @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
40
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41
 */
42
class behat_mod_bigbluebuttonbn extends behat_base {
43
    use subplugins_test_helper_trait;
44
 
45
    /**
46
     * @var array List of installed subplugins.
47
     */
48
    protected $installedsubplugins = [];
49
 
50
    /**
51
     * BeforeScenario hook to reset the remote testpoint.
52
     *
53
     * @BeforeScenario @mod_bigbluebuttonbn
54
     *
55
     * @param BeforeScenarioScope $scope
56
     */
57
    public function before_scenario(BeforeScenarioScope $scope) {
58
        if (defined('TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER')) {
59
            $this->send_mock_request('backoffice/reset');
60
        }
61
        // Fields are empty by default which causes tests to fail.
62
        set_config('bigbluebuttonbn_server_url', config::DEFAULT_SERVER_URL);
63
        set_config('bigbluebuttonbn_shared_secret', config::DEFAULT_SHARED_SECRET);
64
    }
65
 
66
    /**
67
     * Check that the TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER is defined, so we can connect to the mock server.
68
     *
69
     * @Given /^a BigBlueButton mock server is configured$/
70
     */
71
    public function mock_is_configured(): void {
72
        if (!defined('TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER')) {
73
            throw new SkippedException(
74
                'The TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER constant must be defined to run mod_bigbluebuttonbn tests'
75
            );
76
        }
77
 
78
        set_config('bigbluebuttonbn_server_url', TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER);
79
    }
80
 
81
    /**
82
     * Return the list of exact named selectors.
83
     *
84
     * @return array
85
     */
86
    public static function get_exact_named_selectors(): array {
87
        return [
88
            new behat_component_named_selector('Meeting field', [
89
                <<<XPATH
90
    .//*[@data-identifier=%locator%]
91
XPATH
92
            ], false),
93
        ];
94
    }
95
 
96
    /**
97
     * Retrieve the mock server URL from the TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER definition
98
     *
99
     * @param string $endpoint
100
     * @param array $params
101
     * @return moodle_url
102
     */
103
    public static function get_mocked_server_url(string $endpoint = '', array $params = []): moodle_url {
104
        return new moodle_url(TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER . '/' . $endpoint, $params);
105
    }
106
 
107
    /**
108
     * Send a query to the mock server
109
     *
110
     * @param string $endpoint
111
     * @param array $params
112
     */
113
    protected function send_mock_request(string $endpoint, array $params = []): void {
114
        $url = $this->get_mocked_server_url($endpoint, $params);
115
 
116
        $curl = new \curl();
117
        $curl->get($url->out_omit_querystring(), $url->params());
118
    }
119
 
120
    /**
121
     * Convert page names to URLs for steps like 'When I am on the "[page name]" page'.
122
     *
123
     * Recognised page names are:
124
     * | None so far!      |                                                              |
125
     *
126
     * @param string $page name of the page, with the component name removed e.g. 'Admin notification'.
127
     * @return moodle_url the corresponding URL.
128
     * @throws Exception with a meaningful error message if the specified page cannot be found.
129
     */
130
    protected function resolve_page_url(string $page): moodle_url {
131
        throw new Exception("Unrecognised page type '{$page}'.");
132
    }
133
 
134
    /**
135
     * Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'.
136
     *
137
     * Recognised page names are:
138
     * | pagetype | name meaning     | description                    |
139
     * | Index    | BBB Course Index | The bbb index page (index.php) |
140
     *
141
     * @param string $type identifies which type of page this is, e.g. 'Indez'.
142
     * @param string $identifier identifies the particular page, e.g. 'Mathematics 101'.
143
     * @return moodle_url the corresponding URL.
144
     * @throws Exception with a meaningful error message if the specified page cannot be found.
145
     */
146
    protected function resolve_page_instance_url(string $type, string $identifier): moodle_url {
147
        switch ($type) {
148
            case 'Index':
149
                $this->get_course_id($identifier);
150
                return new moodle_url('/mod/bigbluebuttonbn/index.php', [
151
                    'id' => $this->get_course_id($identifier),
152
                ]);
153
            case 'BigblueButtonBN Guest':
154
                $cm = $this->get_cm_by_activity_name('bigbluebuttonbn', $identifier);
155
                $instance = instance::get_from_cmid($cm->id);
156
                $url = $instance->get_guest_access_url();
157
                // We have to make sure we set the password. It makes it then easy to submit the form with the right password.
158
                $url->param('password', $instance->get_guest_access_password());
159
                return $url;
160
            default:
161
                throw new Exception("Unrecognised page type '{$type}'.");
162
        }
163
    }
164
 
165
    /**
166
     * Get course id from its identifier (shortname or fullname or idnumber)
167
     *
168
     * @param string $identifier
169
     * @return int
170
     */
171
    protected function get_course_id(string $identifier): int {
172
        global $DB;
173
 
174
        return $DB->get_field_select(
175
            'course',
176
            'id',
177
            "shortname = :shortname OR fullname = :fullname OR idnumber = :idnumber",
178
            [
179
                'shortname' => $identifier,
180
                'fullname' => $identifier,
181
                'idnumber' => $identifier,
182
            ],
183
            MUST_EXIST
184
        );
185
    }
186
 
187
    /**
188
     * Trigger a recording ready notification on BBB side
189
     *
190
     * @Given the BigBlueButtonBN server has sent recording ready notifications
191
     */
192
    public function trigger_recording_ready_notification(): void {
193
        $this->send_mock_request('backoffice/sendRecordingReadyNotifications', [
194
                'secret' => \mod_bigbluebuttonbn\local\config::DEFAULT_SHARED_SECRET,
195
            ]
196
        );
197
    }
198
 
199
    /**
200
     * Trigger a meeting event on BBB side
201
     *
202
     * @Given /^the BigBlueButtonBN server has received the following events from user "(?P<element_string>(?:[^"]|\\")*)":$/
203
     * @param string $username
204
     * @param TableNode $data
205
     */
206
    public function trigger_meeting_event(string $username, TableNode $data): void {
207
        global $DB;
208
        $user = core_user::get_user_by_username($username);
209
        $rows = $data->getHash();
210
        foreach ($rows as $elementdata) {
211
            $instanceid = $DB->get_field('bigbluebuttonbn', 'id', [
212
                'name' => $elementdata['instancename'],
213
            ]);
214
            $instance = \mod_bigbluebuttonbn\instance::get_from_instanceid($instanceid);
215
            $this->send_mock_request('backoffice/addMeetingEvent', [
216
                    'secret' => \mod_bigbluebuttonbn\local\config::DEFAULT_SHARED_SECRET,
217
                    'meetingID' => $instance->get_meeting_id(),
218
                    'attendeeID' => $user->id,
219
                    'attendeeName' => fullname($user),
220
                    'eventType' => $elementdata['eventtype'],
221
                    'eventData' => $elementdata['eventdata'] ?? '',
222
                ]
223
            );
224
        }
225
    }
226
    /**
227
     * Send all events received for this meeting back to moodle
228
     *
229
     * @Given /^the BigBlueButtonBN activity "(?P<element_string>(?:[^"]|\\")*)" has sent recording all its events$/
230
     * @param string $instancename
231
     */
232
    public function trigger_all_events(string $instancename): void {
233
        global $DB;
234
 
235
        $instanceid = $DB->get_field('bigbluebuttonbn', 'id', [
236
            'name' => $instancename,
237
        ]);
238
        $instance = \mod_bigbluebuttonbn\instance::get_from_instanceid($instanceid);
239
        $this->send_mock_request('backoffice/sendAllEvents', [
240
                'meetingID' => $instance->get_meeting_id(),
241
                'sendQuery' => true
242
            ]
243
        );
244
    }
245
 
246
    /**
247
     * Install the simple subplugin
248
     *
249
     * Important note here. Originally we had a step that was installing the plugin, however
250
     * because of race condition (mainly javascript calls), the hack to the core_component was
251
     * randomly lost due to the component cache being cleared. So we have to install the plugin before
252
     * any interaction with the site.
253
     * @BeforeScenario @with_bbbext_simple
254
     */
255
    public function install_simple_subplugin() {
256
        $this->setup_fake_plugin("simple");
257
        $mockedcomponent = new ReflectionClass(core_component::class);
258
        $mockedplugintypes = $mockedcomponent->getProperty('plugintypes');
259
        $mockedplugintypes->setValue(null, null);
260
        $init = $mockedcomponent->getMethod('init');
261
        $init->invoke(null);
262
        // I enable the plugin.
263
        $manager = core_plugin_manager::resolve_plugininfo_class(\mod_bigbluebuttonbn\extension::BBB_EXTENSION_PLUGIN_NAME);
264
        $manager::enable_plugin("simple", true);
265
    }
266
 
267
    /**
268
     * Uninstall the simple subplugin
269
     *
270
     * @AfterScenario @with_bbbext_simple
271
     */
272
    public function uninstall_simple_subplugin() {
273
        $this->uninstall_fake_plugin("simple");
274
    }
275
}