Completed
Push — master ( a4ccc9...80b84c )
by John
02:43
created

canUseXRouterControllerForDiKeyInOperation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 16

Duplication

Lines 23
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 23
loc 23
rs 9.0856
cc 1
eloc 16
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 canUseXRouterMethodToOverrideMethod()
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
        $pathDefinitions = (object)[
205
            '/a'       => (object)[
206
                'get'  => (object)[],
207
                'post' => (object)['x-router-controller-method' => 'myMethodName']
208
            ],
209
            '/b'       => (object)['get' => (object)[]],
210
        ];
211
212
        $this->documentMock
213
            ->expects($this->any())
214
            ->method('getPathDefinitions')
215
            ->willReturn($pathDefinitions);
216
217
        $routes = $this->loader->load(self::DOCUMENT_PATH);
218
219
        $actual = $routes->get('swagger.path.a.myMethodName');
220
        $this->assertNotNull($actual);
221
    }
222
223
    /**
224
     * @test
225
     */
226 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...
227
    {
228
        $diKey = 'my.x_router.controller';
229
        $expected = "$diKey:post";
230
        $pathDefinitions = (object)[
231
            '/a' => (object)[
232
                'get'  => (object)[],
233
                'post' => (object)['x-router-controller' => $diKey]
234
            ],
235
            '/b' => (object)['get' => (object)[]],
236
        ];
237
238
        $this->documentMock
239
            ->expects($this->any())
240
            ->method('getPathDefinitions')
241
            ->willReturn($pathDefinitions);
242
243
        $routes = $this->loader->load(self::DOCUMENT_PATH);
244
245
        $actual = $routes->get('swagger.path.a.post');
246
        $this->assertNotNull($actual);
247
        $this->assertSame($expected, $actual->getDefault('_controller'));
248
    }
249
250
    /**
251
     * @test
252
     */
253 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...
254
    {
255
        $diKey = 'my.x_router.controller';
256
        $expected = "$diKey:post";
257
        $pathDefinitions = (object)[
258
            '/a' => (object)[
259
                'x-router-controller' => $diKey,
260
                'get'                 => (object)[],
261
                'post'                => (object)[]
262
            ],
263
            '/b' => (object)['get' => (object)[]],
264
        ];
265
266
        $this->documentMock
267
            ->expects($this->any())
268
            ->method('getPathDefinitions')
269
            ->willReturn($pathDefinitions);
270
271
        $routes = $this->loader->load(self::DOCUMENT_PATH);
272
273
        $actual = $routes->get('swagger.path.a.post');
274
        $this->assertNotNull($actual);
275
        $this->assertSame($expected, $actual->getDefault('_controller'));
276
    }
277
278
    /**
279
     * @test
280
     */
281 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...
282
    {
283
        $router = 'my.x_router';
284
        $expected = "$router.a:post";
285
        $pathDefinitions = (object)[
286
            'x-router' => $router,
287
            '/a'       => (object)[
288
                'get'  => (object)[],
289
                'post' => (object)[]
290
            ],
291
            '/b'       => (object)['get' => (object)[]],
292
        ];
293
294
        $this->documentMock
295
            ->expects($this->any())
296
            ->method('getPathDefinitions')
297
            ->willReturn($pathDefinitions);
298
299
        $routes = $this->loader->load(self::DOCUMENT_PATH);
300
301
        $actual = $routes->get('swagger.path.a.post');
302
        $this->assertNotNull($actual);
303
        $this->assertSame($expected, $actual->getDefault('_controller'));
304
    }
305
306
    /**
307
     * @test
308
     */
309 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...
310
    {
311
        $pathDefinitions = (object)[
312
            '/a'     => (object)['get' => (object)[]],
313
            '/a/b'   => (object)['get' => (object)[], 'post' => (object)[]],
314
            '/a/b/c' => (object)['put' => (object)[]],
315
        ];
316
317
        $this->documentMock
318
            ->expects($this->any())
319
            ->method('getPathDefinitions')
320
            ->willReturn($pathDefinitions);
321
322
        $routes = $this->loader->load(self::DOCUMENT_PATH);
323
324
        $this->assertCount(4, $routes);
325
    }
326
327
    /**
328
     * @test
329
     */
330
    public function routeCollectionWillContainPathFromSwaggerDoc()
331
    {
332
        $pathDefinitions = (object)[
333
            '/a'                => (object)['get' => (object)[]],
334
            '/a/b'              => (object)['get' => (object)[]],
335
            '/a/b/c'            => (object)['get' => (object)[]],
336
            '/d/f/g'            => (object)['get' => (object)[]],
337
            '/1/2/3'            => (object)['get' => (object)[]],
338
            '/foo/{bar}/{blah}' => (object)['get' => (object)[]],
339
            '/z'                => (object)['get' => (object)[]],
340
        ];
341
342
        $this->documentMock
343
            ->expects($this->any())
344
            ->method('getPathDefinitions')
345
            ->willReturn($pathDefinitions);
346
347
        $routes = $this->loader->load(self::DOCUMENT_PATH);
348
349
        $definitionPaths = array_keys((array)$pathDefinitions);
350
        sort($definitionPaths);
351
        $routePaths = array_map(function ($route) {
352
            return $route->getPath();
353
        }, $routes->getIterator()->getArrayCopy());
354
        sort($routePaths);
355
        $this->assertSame($definitionPaths, $routePaths);
356
    }
357
358
    /**
359
     * @test
360
     */
361
    public function willAddRequirementsForIntegerPathParams()
362
    {
363
        $pathDefinitions = (object)[
364
            '/a' => (object)[
365
                'get' => (object)[
366
                    'parameters' => (object)[
367
                        (object)['name' => 'foo', 'in' => 'path', 'type' => 'integer']
368
                    ]
369
                ]
370
            ],
371
        ];
372
373
        $this->documentMock
374
            ->expects($this->any())
375
            ->method('getPathDefinitions')
376
            ->willReturn($pathDefinitions);
377
378
        $routes = $this->loader->load(self::DOCUMENT_PATH);
379
        $actual = $routes->get('swagger.path.a.get');
380
        $this->assertNotNull($actual);
381
        $requirements = $actual->getRequirements();
382
        $this->assertNotNull($requirements);
383
384
        $this->assertSame($requirements['foo'], '\d+');
385
    }
386
387
    /**
388
     * @test
389
     */
390
    public function willAddRequirementsForStringPatternParams()
391
    {
392
        $expected = '\d{2}hello';
393
        $pathDefinitions = (object)[
394
            '/a' => (object)[
395
                'get' => (object)[
396
                    'parameters' => (object)[
397
                        (object)['name' => 'aString', 'in' => 'path', 'type' => 'string', 'pattern' => $expected]
398
                    ]
399
                ]
400
            ],
401
        ];
402
403
        $this->documentMock
404
            ->expects($this->any())
405
            ->method('getPathDefinitions')
406
            ->willReturn($pathDefinitions);
407
408
        $routes = $this->loader->load(self::DOCUMENT_PATH);
409
        $actual = $routes->get('swagger.path.a.get');
410
        $this->assertNotNull($actual);
411
        $requirements = $actual->getRequirements();
412
        $this->assertNotNull($requirements);
413
414
        $this->assertSame($expected, $requirements['aString']);
415
    }
416
417
    /**
418
     * @test
419
     */
420
    public function willAddRequirementsForStringEnumParams()
421
    {
422
        $enum = ['a', 'b', 'c'];
423
        $expected = '(a|b|c)';
424
        $pathDefinitions = (object)[
425
            '/a' => (object)[
426
                'get' => (object)[
427
                    'parameters' => (object)[
428
                        (object)['name' => 'aString', 'in' => 'path', 'type' => 'string', 'enum' => $enum]
429
                    ]
430
                ]
431
            ],
432
        ];
433
434
        $this->documentMock
435
            ->expects($this->any())
436
            ->method('getPathDefinitions')
437
            ->willReturn($pathDefinitions);
438
439
        $routes = $this->loader->load(self::DOCUMENT_PATH);
440
        $actual = $routes->get('swagger.path.a.get');
441
        $this->assertNotNull($actual);
442
        $requirements = $actual->getRequirements();
443
        $this->assertNotNull($requirements);
444
445
        $this->assertSame($expected, $requirements['aString']);
446
    }
447
}
448