Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
namespace communication_matrix;
18
 
19
use communication_matrix\local\command;
20
use communication_matrix\local\spec\v1p7;
21
use communication_matrix\local\spec\features;
22
use communication_matrix\tests\fixtures\mocked_matrix_client;
23
use GuzzleHttp\Handler\MockHandler;
24
use GuzzleHttp\Psr7\Response;
25
use moodle_exception;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
require_once(__DIR__ . '/matrix_client_test_trait.php');
29
 
30
/**
31
 * Tests for the matrix_client class.
32
 *
33
 * @package    communication_matrix
34
 * @category   test
35
 * @copyright  2023 Andrew Lyons <andrew@nicols.co.uk>
36
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 * @covers \communication_matrix\matrix_client
38
 * @coversDefaultClass \communication_matrix\matrix_client
39
 */
1441 ariadna 40
final class matrix_client_test extends \advanced_testcase {
1 efrain 41
    use matrix_client_test_trait;
42
 
43
    /**
44
     * Data provider for valid calls to ::instance.
45
     * @return array
46
     */
47
    public static function instance_provider(): array {
48
        $testcases = [
49
            'Standard versions' => [
50
                null,
51
                v1p7::class,
52
            ],
53
        ];
54
 
55
        // Remove a couple of versions.
56
        $versions = self::get_current_versions();
57
        array_pop($versions);
58
        array_pop($versions);
59
 
60
        $testcases['Older server'] = [
61
            $versions,
62
            array_key_last($versions),
63
        ];
64
 
65
        // Limited version compatibility, including newer than we support now.
66
        $testcases['Newer versions with crossover'] = [
67
            [
68
                'v1.6',
69
                'v1.7',
70
                'v7.9',
71
            ],
72
            \communication_matrix\local\spec\v1p7::class,
73
        ];
74
 
75
        return $testcases;
76
    }
77
 
78
    /**
79
     * Test that the instance method returns a valid instance for the given versions.
80
     *
81
     * @dataProvider instance_provider
82
     * @param array|null $versions
83
     * @param string $expectedversion
84
     */
85
    public function test_instance(
86
        ?array $versions,
87
        string $expectedversion,
88
    ): void {
1441 ariadna 89
        $container = [];
90
        ['client' => $client, 'mock' => $mock] = $this->get_mocked_http_client(
91
            history: $container,
92
        );
1 efrain 93
 
1441 ariadna 94
        $mock->append($this->get_mocked_version_response($versions));
95
 
1 efrain 96
        mocked_matrix_client::set_client($client);
97
 
98
        $instance = mocked_matrix_client::instance(
99
            'https://example.com',
100
            'testtoken',
101
        );
102
 
103
        $this->assertInstanceOf(matrix_client::class, $instance);
104
 
105
        // Only the version API has been called.
106
        $this->assertCount(1, $container);
107
        $request = reset($container);
108
        $this->assertEquals('/_matrix/client/versions', $request['request']->getUri()->getPath());
109
 
110
        // The client should be a v1p7 client as that is the highest compatible version.
111
        $this->assertInstanceOf($expectedversion, $instance);
112
    }
113
 
114
    /**
115
     * Test that the instance method returns a valid instance for the given versions.
116
     */
117
    public function test_instance_cached(): void {
118
        $container = [];
1441 ariadna 119
        ['client' => $client, 'mock' => $mock] = $this->get_mocked_http_client(
120
            history: $container,
121
        );
122
 
123
        // Queue two responses.
124
        $mock->append($this->get_mocked_version_response());
125
        $mock->append($this->get_mocked_version_response());
126
 
1 efrain 127
        mocked_matrix_client::set_client($client);
128
 
129
        $instance = mocked_matrix_client::instance('https://example.com', 'testtoken');
130
 
131
        $this->assertInstanceOf(matrix_client::class, $instance);
132
 
133
        // Only the version API has been called.
134
        $this->assertCount(1, $container);
135
 
136
        // Call the API again. It should not lead to additional fetches.
137
        $instance = mocked_matrix_client::instance('https://example.com', 'testtoken');
138
        $instance = mocked_matrix_client::instance('https://example.com', 'testtoken');
139
        $this->assertCount(1, $container);
140
 
141
        // But a different endpoint will.
142
        $instance = mocked_matrix_client::instance('https://example.org', 'testtoken');
143
        $this->assertCount(2, $container);
144
    }
145
 
146
    /**
147
     * Test that the instance method throws an appropriate exception if no support is found.
148
     */
149
    public function test_instance_no_support(): void {
1441 ariadna 150
        ['client' => $client, 'mock' => $mock] = $this->get_mocked_http_client();
1 efrain 151
 
1441 ariadna 152
        $mock->append($this->get_mocked_version_response(['v99.9']));
153
 
1 efrain 154
        mocked_matrix_client::set_client($client);
155
 
156
        $this->expectException(moodle_exception::class);
157
        $this->expectExceptionMessage('No supported Matrix API versions found.');
158
 
159
        mocked_matrix_client::instance(
160
            'https://example.com',
161
            'testtoken',
162
        );
163
    }
164
 
165
    /**
166
     * Test the feature implementation check methods.
167
     *
168
     * @covers ::implements_feature
169
     * @covers ::get_supported_versions
170
     * @dataProvider implements_feature_provider
171
     * @param string $version
172
     * @param array|string $features
173
     * @param bool $expected
174
     */
175
    public function test_implements_feature(
176
        string $version,
177
        array|string $features,
178
        bool $expected,
179
    ): void {
180
        $instance = $this->get_mocked_instance_for_version($version);
181
        $this->assertEquals($expected, $instance->implements_feature($features));
182
    }
183
 
184
    /**
185
     * Test the feature implementation requirement methods.
186
     *
187
     * @covers ::implements_feature
188
     * @covers ::get_supported_versions
189
     * @covers ::require_feature
190
     * @dataProvider implements_feature_provider
191
     * @param string $version
192
     * @param array|string $features
193
     * @param bool $expected
194
     */
195
    public function test_require_feature(
196
        string $version,
197
        array|string $features,
198
        bool $expected,
199
    ): void {
200
        $instance = $this->get_mocked_instance_for_version($version);
201
 
202
        if ($expected) {
203
            $this->assertEmpty($instance->require_feature($features));
204
        } else {
205
            $this->expectException('moodle_exception');
206
            $instance->require_feature($features);
207
        }
208
    }
209
 
210
    /**
211
     * Test the feature implementation requirement methods for a require all.
212
     *
213
     * @covers ::implements_feature
214
     * @covers ::get_supported_versions
215
     * @covers ::require_feature
216
     * @covers ::require_features
217
     * @dataProvider require_features_provider
218
     * @param string $version
219
     * @param array|string $features
220
     * @param bool $expected
221
     */
222
    public function test_require_features(
223
        string $version,
224
        array|string $features,
225
        bool $expected,
226
    ): void {
227
        $instance = $this->get_mocked_instance_for_version($version);
228
 
229
        if ($expected) {
230
            $this->assertEmpty($instance->require_features($features));
231
        } else {
232
            $this->expectException('moodle_exception');
233
            $instance->require_features($features);
234
        }
235
    }
236
 
237
    /**
238
     * Data provider for feature implementation check tests.
239
     *
240
     * @return array
241
     */
242
    public static function implements_feature_provider(): array {
243
        return [
244
            'Basic supported feature' => [
245
                'v1.7',
246
                features\matrix\media_create_v1::class,
247
                true,
248
            ],
249
            'Basic unsupported feature' => [
250
                'v1.6',
251
                features\matrix\media_create_v1::class,
252
                false,
253
            ],
254
            '[supported] as array' => [
255
                'v1.6',
256
                [features\matrix\create_room_v3::class],
257
                true,
258
            ],
259
            '[supported, supported] as array' => [
260
                'v1.6',
261
                [
262
                    features\matrix\create_room_v3::class,
263
                    features\matrix\update_room_avatar_v3::class,
264
                ],
265
                true,
266
            ],
267
            '[unsupported] as array' => [
268
                'v1.6',
269
                [
270
                    features\matrix\media_create_v1::class,
271
                ],
272
                false,
273
            ],
274
            '[unsupported, supported] as array' => [
275
                'v1.6',
276
                [
277
                    features\matrix\media_create_v1::class,
278
                    features\matrix\update_room_avatar_v3::class,
279
                ],
280
                true,
281
            ],
282
        ];
283
    }
284
 
285
    /**
286
     * Data provider for feature implementation check tests.
287
     *
288
     * @return array
289
     */
290
    public static function require_features_provider(): array {
291
        // We'll just add to the standard testcases.
292
        $testcases = array_map(static function (array $testcase): array {
293
            $testcase[1] = [$testcase[1]];
294
            return $testcase;
295
        }, self::implements_feature_provider());
296
 
297
        $testcases['Require many supported features'] = [
298
            'v1.6',
299
            [
300
                features\matrix\create_room_v3::class,
301
                features\matrix\update_room_avatar_v3::class,
302
            ],
303
            true,
304
        ];
305
 
306
        $testcases['Require many including an unsupported feature'] = [
307
            'v1.6',
308
            [
309
                features\matrix\create_room_v3::class,
310
                features\matrix\media_create_v1::class,
311
            ],
312
            false,
313
        ];
314
 
315
        $testcases['Require many including an unsupported feature which has an alternate'] = [
316
            'v1.6',
317
            [
318
                features\matrix\create_room_v3::class,
319
                [
320
                    features\matrix\media_create_v1::class,
321
                    features\matrix\update_room_avatar_v3::class,
322
                ],
323
            ],
324
            true,
325
        ];
326
 
327
        return $testcases;
328
    }
329
 
330
    /**
331
     * Test the get_version method.
332
     *
333
     * @param string $version
334
     * @param string $expectedversion
335
     * @dataProvider get_version_provider
336
     * @covers ::get_version
337
     * @covers ::get_version_from_classname
338
     */
339
    public function test_get_version(
340
        string $version,
341
        string $expectedversion,
342
    ): void {
343
        $instance = $this->get_mocked_instance_for_version($version);
344
        $this->assertEquals($expectedversion, $instance->get_version());
345
    }
346
 
347
    /**
348
     * Data provider for get_version tests.
349
     *
350
     * @return array
351
     */
352
    public static function get_version_provider(): array {
353
        return [
354
            ['v1.1', '1.1'],
355
            ['v1.7', '1.7'],
356
        ];
357
    }
358
 
359
    /**
360
     * Tests the meets_version method.
361
     *
362
     * @param string $version The version of the API to test against
363
     * @param string $testversion The version to test
364
     * @param bool $expected Whether the version meets the requirement
365
     * @dataProvider meets_version_provider
366
     * @covers ::meets_version
367
     */
368
    public function test_meets_version(
369
        string $version,
370
        string $testversion,
371
        bool $expected,
372
    ): void {
373
        $instance = $this->get_mocked_instance_for_version($version);
374
        $this->assertEquals($expected, $instance->meets_version($testversion));
375
    }
376
 
377
    /**
378
     * Tests the requires_version method.
379
     *
380
     * @param string $version The version of the API to test against
381
     * @param string $testversion The version to test
382
     * @param bool $expected Whether the version meets the requirement
383
     * @dataProvider meets_version_provider
384
     * @covers ::requires_version
385
     */
386
    public function test_requires_version(
387
        string $version,
388
        string $testversion,
389
        bool $expected,
390
    ): void {
391
        $instance = $this->get_mocked_instance_for_version($version);
392
 
393
        if ($expected) {
394
            $this->assertEmpty($instance->requires_version($testversion));
395
        } else {
396
            $this->expectException('moodle_exception');
397
            $instance->requires_version($testversion);
398
        }
399
    }
400
 
401
    /**
402
     * Data provider for meets_version tests.
403
     *
404
     * @return array
405
     */
406
    public static function meets_version_provider(): array {
407
        return [
408
            'Same version' => ['v1.1', '1.1', true],
409
            'Same version latest' => ['v1.7', '1.7', true],
410
            'Newer version rejected' => ['v1.1', '1.7', false],
411
            'Older version accepted' => ['v1.7', '1.1', true],
412
        ];
413
    }
414
 
415
    /**
416
     * Test the execute method with a command.
417
     *
418
     * @covers ::execute
419
     */
420
    public function test_command_is_executed(): void {
421
        $historycontainer = [];
422
        $mock = new MockHandler();
423
 
424
        $instance = $this->get_mocked_instance_for_version('v1.6', $historycontainer, $mock);
425
        $command = new command(
426
            $instance,
427
            method: 'GET',
428
            endpoint: 'test/endpoint',
429
            params: [
430
                'test' => 'test',
431
            ],
432
        );
433
 
434
        $mock->append(new Response(200));
435
 
436
        $rc = new \ReflectionClass($instance);
437
        $rcm = $rc->getMethod('execute');
438
        $result = $rcm->invoke($instance, $command);
439
 
440
        $this->assertEquals(200, $result->getStatusCode());
441
        $this->assertCount(1, $historycontainer);
442
        $request = array_shift($historycontainer);
443
        $this->assertEquals('GET', $request['request']->getMethod());
444
        $this->assertEquals('/test/endpoint', $request['request']->getUri()->getPath());
445
    }
446
}