Completed
Push — master ( 864e6f...2fb823 )
by John
8s
created

routeCollectionWillContainPathFromSwaggerDoc()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 27
rs 8.8571
cc 1
eloc 21
nc 1
nop 0
1
<?php
2
/*
3
 * This file is part of the KleijnWeb\SwaggerBundle package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace KleijnWeb\SwaggerBundle\Tests\Routing;
10
11
use KleijnWeb\SwaggerBundle\Routing\SwaggerRouteLoader;
12
13
/**
14
 * @author John Kleijn <[email protected]>
15
 */
16
class SwaggerRouteLoaderTest extends \PHPUnit_Framework_TestCase
17
{
18
    const DOCUMENT_PATH = '/totally/non-existent/path';
19
20
    /**
21
     * @var \PHPUnit_Framework_MockObject_MockObject
22
     */
23
    private $repositoryMock;
24
25
    /**
26
     * @var \PHPUnit_Framework_MockObject_MockObject
27
     */
28
    private $documentMock;
29
30
    /**
31
     * @var SwaggerRouteLoader
32
     */
33
    private $loader;
34
35
    /**
36
     * Create mocks
37
     */
38
    protected function setUp()
39
    {
40
        $this->documentMock = $this
41
            ->getMockBuilder('KleijnWeb\SwaggerBundle\Document\SwaggerDocument')
42
            ->disableOriginalConstructor()
43
            ->setMethods(['getPathDefinitions'])
44
            ->getMock();
45
46
        $this->repositoryMock = $this
47
            ->getMockBuilder('KleijnWeb\SwaggerBundle\Document\DocumentRepository')
48
            ->disableOriginalConstructor()
49
            ->getMock();
50
51
        $this->repositoryMock
52
            ->expects($this->any())
53
            ->method('get')
54
            ->willReturn($this->documentMock);
55
56
        $this->loader = new SwaggerRouteLoader($this->repositoryMock);
57
    }
58
59
    /**
60
     * @test
61
     */
62
    public function supportSwaggerAsRouteTypeOnly()
63
    {
64
        $this->assertFalse($this->loader->supports('/a/b/c'));
65
        $this->assertTrue($this->loader->supports('/a/b/c', 'swagger'));
66
    }
67
68
    /**
69
     * @test
70
     */
71 View Code Duplication
    public function canLoadMultipleDocuments()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
72
    {
73
        $this->documentMock
74
            ->expects($this->any())
75
            ->method('getPathDefinitions')
76
            ->willReturn([]);
77
78
        $this->loader->load(self::DOCUMENT_PATH);
79
        $this->loader->load(self::DOCUMENT_PATH . '2');
80
    }
81
82
    /**
83
     * @test
84
     */
85
    public function loadingMultipleDocumentWillPreventRouteKeyCollisions()
86
    {
87
        $pathDefinitions = (object)[
88
            '/a'     => (object)['get' => (object)[]],
89
            '/a/b'   => (object)['get' => (object)[], 'post' => (object)[]],
90
            '/a/b/c' => (object)['put' => (object)[]],
91
        ];
92
93
        $this->documentMock
94
            ->expects($this->any())
95
            ->method('getPathDefinitions')
96
            ->willReturn($pathDefinitions);
97
98
        $routes1 = $this->loader->load(self::DOCUMENT_PATH);
99
        $routes2 = $this->loader->load(self::DOCUMENT_PATH . '2');
100
        $this->assertSame(count($routes1), count(array_diff_key($routes1->all(), $routes2->all())));
101
    }
102
103
    /**
104
     * @test
105
     * @expectedException \RuntimeException
106
     */
107 View Code Duplication
    public function cannotTryToLoadSameDocumentMoreThanOnce()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
108
    {
109
        $this->documentMock
110
            ->expects($this->any())
111
            ->method('getPathDefinitions')
112
            ->willReturn([]);
113
114
        $this->loader->load(self::DOCUMENT_PATH);
115
        $this->loader->load(self::DOCUMENT_PATH);
116
    }
117
118
    /**
119
     * @test
120
     */
121 View Code Duplication
    public function willReturnRouteCollection()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
122
    {
123
        $this->documentMock
124
            ->expects($this->any())
125
            ->method('getPathDefinitions')
126
            ->willReturn([]);
127
128
        $routes = $this->loader->load(self::DOCUMENT_PATH);
129
        $this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $routes);
130
    }
131
132
    /**
133
     * @test
134
     */
135
    public function routeCollectionWillContainOneRouteForEveryPathAndMethod()
136
    {
137
        $pathDefinitions = (object)[
138
            '/a' => (object)['get' => (object)[], 'post' => (object)[]],
139
            '/b' => (object)['get' => (object)[]],
140
        ];
141
142
        $this->documentMock
143
            ->expects($this->any())
144
            ->method('getPathDefinitions')
145
            ->willReturn($pathDefinitions);
146
147
        $routes = $this->loader->load(self::DOCUMENT_PATH);
148
149
        $this->assertCount(3, $routes);
150
    }
151
152
    /**
153
     * @test
154
     */
155 View Code Duplication
    public function routeCollectionWillIncludeSeparateRoutesForSubPaths()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
156
    {
157
        $pathDefinitions = (object)[
158
            '/a'     => (object)['get' => (object)[]],
159
            '/a/b'   => (object)['get' => (object)[]],
160
            '/a/b/c' => (object)['get' => (object)[]],
161
        ];
162
163
        $this->documentMock
164
            ->expects($this->any())
165
            ->method('getPathDefinitions')
166
            ->willReturn($pathDefinitions);
167
168
        $routes = $this->loader->load(self::DOCUMENT_PATH);
169
170
        $this->assertCount(3, $routes);
171
    }
172
173
    /**
174
     * @test
175
     */
176 View Code Duplication
    public function canUseOperationIdAsControllerKey()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
177
    {
178
        $expected = 'my.controller.key:methodName';
179
        $pathDefinitions = (object)[
180
            '/a' => (object)[
181
                'get'  => (object)[],
182
                'post' => (object)['operationId' => $expected]
183
            ],
184
            '/b' => (object)['get' => (object)[]],
185
        ];
186
187
        $this->documentMock
188
            ->expects($this->any())
189
            ->method('getPathDefinitions')
190
            ->willReturn($pathDefinitions);
191
192
        $routes = $this->loader->load(self::DOCUMENT_PATH);
193
194
        $actual = $routes->get('swagger.path.a.methodName');
195
        $this->assertNotNull($actual);
196
        $this->assertSame($expected, $actual->getDefault('_controller'));
197
    }
198
199
    /**
200
     * @test
201
     */
202 View Code Duplication
    public function canUseXRouterControllerForDiKeyInOperation()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
203
    {
204
        $diKey = 'my.x_router.controller';
205
        $expected = "$diKey:post";
206
        $pathDefinitions = (object)[
207
            '/a' => (object)[
208
                'get'  => (object)[],
209
                'post' => (object)['x-router-controller' => $diKey]
210
            ],
211
            '/b' => (object)['get' => (object)[]],
212
        ];
213
214
        $this->documentMock
215
            ->expects($this->any())
216
            ->method('getPathDefinitions')
217
            ->willReturn($pathDefinitions);
218
219
        $routes = $this->loader->load(self::DOCUMENT_PATH);
220
221
        $actual = $routes->get('swagger.path.a.post');
222
        $this->assertNotNull($actual);
223
        $this->assertSame($expected, $actual->getDefault('_controller'));
224
    }
225
226
    /**
227
     * @test
228
     */
229 View Code Duplication
    public function canUseXRouterControllerForDiKeyInPath()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230
    {
231
        $diKey = 'my.x_router.controller';
232
        $expected = "$diKey:post";
233
        $pathDefinitions = (object)[
234
            '/a' => (object)[
235
                'x-router-controller' => $diKey,
236
                'get'                 => (object)[],
237
                'post'                => (object)[]
238
            ],
239
            '/b' => (object)['get' => (object)[]],
240
        ];
241
242
        $this->documentMock
243
            ->expects($this->any())
244
            ->method('getPathDefinitions')
245
            ->willReturn($pathDefinitions);
246
247
        $routes = $this->loader->load(self::DOCUMENT_PATH);
248
249
        $actual = $routes->get('swagger.path.a.post');
250
        $this->assertNotNull($actual);
251
        $this->assertSame($expected, $actual->getDefault('_controller'));
252
    }
253
254
    /**
255
     * @test
256
     */
257 View Code Duplication
    public function canUseXRouterForDiKeyInPath()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
258
    {
259
        $router = 'my.x_router';
260
        $expected = "$router.a:post";
261
        $pathDefinitions = (object)[
262
            'x-router' => $router,
263
            '/a'       => (object)[
264
                'get'  => (object)[],
265
                'post' => (object)[]
266
            ],
267
            '/b'       => (object)['get' => (object)[]],
268
        ];
269
270
        $this->documentMock
271
            ->expects($this->any())
272
            ->method('getPathDefinitions')
273
            ->willReturn($pathDefinitions);
274
275
        $routes = $this->loader->load(self::DOCUMENT_PATH);
276
277
        $actual = $routes->get('swagger.path.a.post');
278
        $this->assertNotNull($actual);
279
        $this->assertSame($expected, $actual->getDefault('_controller'));
280
    }
281
282
    /**
283
     * @test
284
     */
285 View Code Duplication
    public function routeCollectionWillIncludeSeparateRoutesForSubPathMethodCombinations()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
286
    {
287
        $pathDefinitions = (object)[
288
            '/a'     => (object)['get' => (object)[]],
289
            '/a/b'   => (object)['get' => (object)[], 'post' => (object)[]],
290
            '/a/b/c' => (object)['put' => (object)[]],
291
        ];
292
293
        $this->documentMock
294
            ->expects($this->any())
295
            ->method('getPathDefinitions')
296
            ->willReturn($pathDefinitions);
297
298
        $routes = $this->loader->load(self::DOCUMENT_PATH);
299
300
        $this->assertCount(4, $routes);
301
    }
302
303
    /**
304
     * @test
305
     */
306
    public function routeCollectionWillContainPathFromSwaggerDoc()
307
    {
308
        $pathDefinitions = (object)[
309
            '/a'                => (object)['get' => (object)[]],
310
            '/a/b'              => (object)['get' => (object)[]],
311
            '/a/b/c'            => (object)['get' => (object)[]],
312
            '/d/f/g'            => (object)['get' => (object)[]],
313
            '/1/2/3'            => (object)['get' => (object)[]],
314
            '/foo/{bar}/{blah}' => (object)['get' => (object)[]],
315
            '/z'                => (object)['get' => (object)[]],
316
        ];
317
318
        $this->documentMock
319
            ->expects($this->any())
320
            ->method('getPathDefinitions')
321
            ->willReturn($pathDefinitions);
322
323
        $routes = $this->loader->load(self::DOCUMENT_PATH);
324
325
        $definitionPaths = array_keys((array)$pathDefinitions);
326
        sort($definitionPaths);
327
        $routePaths = array_map(function ($route) {
328
            return $route->getPath();
329
        }, $routes->getIterator()->getArrayCopy());
330
        sort($routePaths);
331
        $this->assertSame($definitionPaths, $routePaths);
332
    }
333
334
    /**
335
     * @test
336
     */
337
    public function willAddRequirementsForIntegerPathParams()
338
    {
339
        $pathDefinitions = (object)[
340
            '/a' => (object)[
341
                'get' => (object)[
342
                    'parameters' => (object)[
343
                        (object)['name' => 'foo', 'in' => 'path', 'type' => 'integer']
344
                    ]
345
                ]
346
            ],
347
        ];
348
349
        $this->documentMock
350
            ->expects($this->any())
351
            ->method('getPathDefinitions')
352
            ->willReturn($pathDefinitions);
353
354
        $routes = $this->loader->load(self::DOCUMENT_PATH);
355
        $actual = $routes->get('swagger.path.a.get');
356
        $this->assertNotNull($actual);
357
        $requirements = $actual->getRequirements();
358
        $this->assertNotNull($requirements);
359
360
        $this->assertSame($requirements['foo'], '\d+');
361
    }
362
363
    /**
364
     * @test
365
     */
366
    public function willAddRequirementsForStringPatternParams()
367
    {
368
        $expected = '\d{2}hello';
369
        $pathDefinitions = (object)[
370
            '/a' => (object)[
371
                'get' => (object)[
372
                    'parameters' => (object)[
373
                        (object)['name' => 'aString', 'in' => 'path', 'type' => 'string', 'pattern' => $expected]
374
                    ]
375
                ]
376
            ],
377
        ];
378
379
        $this->documentMock
380
            ->expects($this->any())
381
            ->method('getPathDefinitions')
382
            ->willReturn($pathDefinitions);
383
384
        $routes = $this->loader->load(self::DOCUMENT_PATH);
385
        $actual = $routes->get('swagger.path.a.get');
386
        $this->assertNotNull($actual);
387
        $requirements = $actual->getRequirements();
388
        $this->assertNotNull($requirements);
389
390
        $this->assertSame($expected, $requirements['aString']);
391
    }
392
393
    /**
394
     * @test
395
     */
396
    public function willAddRequirementsForStringEnumParams()
397
    {
398
        $enum = ['a', 'b', 'c'];
399
        $expected = '(a|b|c)';
400
        $pathDefinitions = (object)[
401
            '/a' => (object)[
402
                'get' => (object)[
403
                    'parameters' => (object)[
404
                        (object)['name' => 'aString', 'in' => 'path', 'type' => 'string', 'enum' => $enum]
405
                    ]
406
                ]
407
            ],
408
        ];
409
410
        $this->documentMock
411
            ->expects($this->any())
412
            ->method('getPathDefinitions')
413
            ->willReturn($pathDefinitions);
414
415
        $routes = $this->loader->load(self::DOCUMENT_PATH);
416
        $actual = $routes->get('swagger.path.a.get');
417
        $this->assertNotNull($actual);
418
        $requirements = $actual->getRequirements();
419
        $this->assertNotNull($requirements);
420
421
        $this->assertSame($expected, $requirements['aString']);
422
    }
423
}
424