Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 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 core\router\schema;
18
 
19
use core\param;
20
use core\router\route;
21
use core\router\schema\parameters\path_parameter;
22
use core\router\schema\response\content\payload_response_type;
23
use core\router\schema\response\response;
24
use core\router\schema\specification;
25
use core\tests\router\route_testcase;
26
 
27
/**
28
 * Tests for the specification.
29
 *
30
 * @package    core
31
 * @copyright  Andrew Lyons <andrew@nicols.co.uk>
32
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 * @covers     \core\router\schema\specification
34
 */
35
final class specification_test extends route_testcase {
36
    public function test_basics(): void {
37
        global $CFG;
38
 
39
        $spec = new specification();
40
        $schema = $spec->get_schema();
41
 
42
        $this->assertIsObject($schema);
43
 
44
        // We comply with OpenAPI 3.1.0.
45
        $this->assertObjectHasProperty('openapi', $schema);
46
        $this->assertEquals('3.1.0', $schema->openapi);
47
 
48
        // INfo should include our license.
49
        $this->assertObjectHasProperty('info', $schema);
50
        $this->assertObjectHasProperty('license', $schema->info);
51
        $this->assertStringContainsString('GNU GPL v3 or later', $schema->info->license->name);
52
        $this->assertObjectHasProperty('url', $schema->info->license);
53
 
54
        // The server list should contain the currenet URI during finalisation.
55
        $this->assertObjectHasProperty('servers', $schema);
56
        $this->assertIsArray($schema->servers);
57
        $this->assertCount(1, $schema->servers);
58
        $server = $schema->servers[0];
59
        $this->assertStringStartsWith($CFG->wwwroot, $server->url);
60
 
61
        $this->assertObjectHasProperty('paths', $schema);
62
        $this->assertObjectHasProperty('components', $schema);
63
        $this->assertObjectHasProperty('security', $schema);
64
        $this->assertObjectHasProperty('externalDocs', $schema);
65
 
66
        // Calculated parameters should only be set once.
67
        $schema = $spec->get_schema();
68
        $this->assertCount(1, $schema->servers);
69
 
70
        $this->assertJson(json_encode($spec));
71
    }
72
 
73
    /**
74
     * Test the add_path method.
75
     *
76
     * @dataProvider add_path_provider
77
     * @param string $component
78
     * @param string $path
79
     * @param string $expectedpath
80
     */
81
    public function test_add_path(
82
        string $component,
83
        string $path,
84
        string $expectedpath,
85
    ): void {
86
        $spec = new specification();
87
 
88
        $spec->add_path(
89
            $component,
90
            new route(
91
                path: $path,
92
            ),
93
        );
94
 
95
        $schema = $spec->get_schema();
96
        $this->assertObjectHasProperty($expectedpath, $schema->paths);
97
    }
98
 
99
    /**
100
     * Data provider for add_path.
101
     *
102
     * @return array
103
     */
104
    public static function add_path_provider(): array {
105
        return [
106
            'Core' => [
107
                'core',
108
                '/example/path',
109
                '/core/example/path',
110
            ],
111
            'Core Subsystem' => [
112
                'core_access',
113
                '/example/path',
114
                '/access/example/path',
115
            ],
116
            'An activity' => [
117
                'mod_assign',
118
                '/example/path',
119
                '/mod_assign/example/path',
120
            ],
121
        ];
122
    }
123
 
124
    public function test_add_path_with_option(): void {
125
        $spec = new specification();
126
 
127
        $spec->add_path(
128
            'core',
129
            new route(
130
                path: '/example/path/with[/{option}]',
131
                pathtypes: [
132
                    new path_parameter(name: 'option', type: param::INT),
133
                ],
134
            ),
135
        );
136
 
137
        $schema = $spec->get_schema();
138
        $this->assertObjectHasProperty('/core/example/path/with', $schema->paths);
139
        $this->assertObjectHasProperty('/core/example/path/with/{option}', $schema->paths);
140
    }
141
 
142
    /**
143
     * Test add_path with optional parameters.
144
     *
145
     * @param string $component
146
     * @param string $path
147
     * @param array $expectedpaths
148
     * @dataProvider add_path_with_options_provider
149
     */
150
    public function test_add_path_with_options(
151
        string $component,
152
        string $path,
153
        array $expectedpaths,
154
    ): void {
155
        $spec = new specification();
156
 
157
        $spec->add_path(
158
            $component,
159
            new route(
160
                path: $path,
161
                pathtypes: [
162
                    new path_parameter(name: 'optional', type: param::INT),
163
                    new path_parameter(name: 'extras', type: param::INT),
164
                ],
165
            ),
166
        );
167
 
168
        $schema = $spec->get_schema();
169
        foreach ($expectedpaths as $expectedpath) {
170
            $this->assertObjectHasProperty($expectedpath, $schema->paths);
171
        }
172
    }
173
 
174
    /**
175
     * Data provider for add_path with optional parameters.
176
     *
177
     * @return \Iterator
178
     */
179
    public static function add_path_with_options_provider(): \Iterator {
180
        yield 'With options' => [
181
            'component' => 'core',
182
            'path' => '/example/path/with[/{optional}][/{extras}]',
183
            'expectedpaths' => [
184
                '/core/example/path/with',
185
                '/core/example/path/with/{optional}',
186
                '/core/example/path/with/{optional}/{extras}',
187
            ],
188
        ];
189
        yield 'With greedy unlimited options' => [
190
            'component' => 'core',
191
            'path' => '/example/path/with[/{optional}][/{extras:.*}]',
192
            'expectedpaths' => [
193
                '/core/example/path/with',
194
                '/core/example/path/with/{optional}',
195
                '/core/example/path/with/{optional}/{extras}',
196
            ],
197
        ];
198
        yield 'With non-greedy unlimited options' => [
199
            'component' => 'core',
200
            'path' => '/example/path/with[/{optional}][/{extras:.*?}]',
201
            'expectedpaths' => [
202
                '/core/example/path/with',
203
                '/core/example/path/with/{optional}',
204
                '/core/example/path/with/{optional}/{extras}',
205
            ],
206
        ];
207
    }
208
 
209
    public function test_add_parameter(): void {
210
        $spec = new specification();
211
 
212
        /** @var path_parameter&\PHPUnit\Framework\MockObject\MockObject $child */
213
        $child = $this->getMockBuilder(path_parameter::class)
214
            ->onlyMethods([])
215
            ->setConstructorArgs([
216
                'name' => 'example',
217
                'type' => param::INT,
218
            ])
219
            ->getMock();
220
 
221
        $this->assertFalse($spec->is_reference_defined($child->get_reference(true)));
222
 
223
        $spec->add_component($child);
224
 
225
        $schema = $spec->get_schema();
226
        $this->assertObjectHasProperty($child->get_reference(false), $schema->components->parameters);
227
        $this->assertTrue($spec->is_reference_defined($child->get_reference(true)));
228
    }
229
 
230
    public function test_add_header(): void {
231
        $spec = new specification();
232
 
233
        /** @var header_object&\PHPUnit\Framework\MockObject\MockObject $child */
234
        $child = $this->getMockBuilder(header_object::class)
235
            ->onlyMethods([])
236
            ->setConstructorArgs([
237
                'name' => 'example',
238
                'type' => param::INT,
239
            ])
240
            ->getMock();
241
 
242
        $this->assertFalse($spec->is_reference_defined($child->get_reference(true)));
243
 
244
        $spec->add_component($child);
245
 
246
        $schema = $spec->get_schema();
247
        $this->assertObjectHasProperty($child->get_reference(false), $schema->components->headers);
248
        $this->assertTrue($spec->is_reference_defined($child->get_reference(true)));
249
    }
250
 
251
    public function test_add_response(): void {
252
        $spec = new specification();
253
 
254
        /** @var response&\PHPUnit\Framework\MockObject\MockObject $child */
255
        $child = $this->getMockBuilder(response::class)
256
            ->onlyMethods([])
257
            ->setConstructorArgs([
258
            ])
259
            ->getMock();
260
 
261
        $this->assertFalse($spec->is_reference_defined($child->get_reference(true)));
262
 
263
        $spec->add_component($child);
264
 
265
        $schema = $spec->get_schema();
266
        $this->assertObjectHasProperty($child->get_reference(false), $schema->components->responses);
267
        $this->assertTrue($spec->is_reference_defined($child->get_reference(true)));
268
    }
269
 
270
    public function test_add_example(): void {
271
        $spec = new specification();
272
 
273
        /** @var example&\PHPUnit\Framework\MockObject\MockObject $child */
274
        $child = $this->getMockBuilder(example::class)
275
            ->onlyMethods([])
276
            ->setConstructorArgs([
277
                'name' => 'An excellent example',
278
            ])
279
            ->getMock();
280
        $this->assertFalse($spec->is_reference_defined($child->get_reference(true)));
281
 
282
        $spec->add_component($child);
283
 
284
        $schema = $spec->get_schema();
285
        $this->assertObjectHasProperty($child->get_reference(false), $schema->components->examples);
286
        $this->assertTrue($spec->is_reference_defined($child->get_reference(true)));
287
    }
288
 
289
    public function test_add_request_body(): void {
290
        $spec = new specification();
291
 
292
        $child = new request_body(
293
            description: 'example',
294
            required: true,
295
        );
296
 
297
        $this->assertFalse($spec->is_reference_defined($child->get_reference(true)));
298
 
299
        $spec->add_component($child);
300
 
301
        $schema = $spec->get_schema();
302
        $this->assertObjectHasProperty($child->get_reference(false), $schema->components->requestBodies);
303
 
304
        $this->assertTrue($spec->is_reference_defined($child->get_reference(true)));
305
 
306
        $requestschema = $spec->get_openapi_schema_for_route(
307
            route: new route(
308
                path: '/example/path',
309
                requestbody: $child,
310
            ),
311
            component: '',
312
            path: '/example/path',
313
        );
314
 
315
        $this->assertObjectHasProperty('requestBody', $requestschema->get);
316
        $this->assertEquals('example', $requestschema->get->requestBody->description);
317
        $this->assertTrue($requestschema->get->requestBody->required);
318
    }
319
 
320
    public function test_route_security_in_schema(): void {
321
        $spec = new specification();
322
 
323
        $route = new route(
324
            path: '/example/path',
325
            security: ['example'],
326
        );
327
 
328
        $spec->add_path(
329
            'core',
330
            $route,
331
        );
332
 
333
        $requestschema = $spec->get_openapi_schema_for_route(
334
            route: $route,
335
            component: '',
336
            path: '/example/path',
337
        );
338
 
339
        $this->assertObjectHasProperty('security', $requestschema->get);
340
        $this->assertEquals(['example'], $requestschema->get->security);
341
    }
342
 
343
    public function test_is_reference_defined(): void {
344
        $spec = new specification();
345
        $this->assertFalse($spec->is_reference_defined('example'));
346
        $this->assertFalse($spec->is_reference_defined('#/components/fake/component'));
347
    }
348
 
349
    public function test_deprecated_route(): void {
350
        $spec = new specification();
351
        $route = new route(
352
            path: '/example/path',
353
            deprecated: true,
354
        );
355
 
356
        $spec->add_path(
357
            'core',
358
            $route,
359
        );
360
 
361
        $requestschema = $spec->get_openapi_schema_for_route(
362
            route: $route,
363
            component: '',
364
            path: '/example/path',
365
        );
366
 
367
        $this->assertObjectHasProperty('deprecated', $requestschema->get);
368
        $this->assertTrue($requestschema->get->deprecated);
369
    }
370
 
371
    public function test_response(): void {
372
        $spec = new specification();
373
        $route = new route(
374
            path: '/example/path',
375
            responses: [
376
                new response(
377
                    status: 200,
378
                    description: 'example',
379
                    content: new payload_response_type(),
380
                ),
381
            ],
382
        );
383
 
384
        $spec->add_path(
385
            'core',
386
            $route,
387
        );
388
 
389
        $requestschema = $spec->get_openapi_schema_for_route(
390
            route: $route,
391
            component: '',
392
            path: '/example/path',
393
        );
394
 
395
        $this->assertObjectHasProperty('responses', $requestschema->get);
396
        $this->assertArrayHasKey('200', $requestschema->get->responses);
397
        $this->assertObjectHasProperty('content', $requestschema->get->responses['200']);
398
        $this->assertObjectHasProperty('application/json', $requestschema->get->responses['200']->content);
399
    }
400
}