Completed
Push — master ( 386146...a2d301 )
by John
07:40
created

routeCollectionWillContainPathFromSwaggerDoc()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 21

Duplication

Lines 0
Ratio 0 %
Metric Value
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
use Symfony\Component\Routing\Route;
13
14
/**
15
 * @author John Kleijn <[email protected]>
16
 */
17
class SwaggerRouteLoaderTest extends \PHPUnit_Framework_TestCase
18
{
19
    const DOCUMENT_PATH = '/totally/non-existent/path';
20
21
    /**
22
     * @var \PHPUnit_Framework_MockObject_MockObject
23
     */
24
    private $repositoryMock;
25
26
    /**
27
     * @var \PHPUnit_Framework_MockObject_MockObject
28
     */
29
    private $documentMock;
30
31
    /**
32
     * @var SwaggerRouteLoader
33
     */
34
    private $loader;
35
36
    /**
37
     * Create mocks
38
     */
39
    protected function setUp()
40
    {
41
        $this->documentMock = $this
42
            ->getMockBuilder('KleijnWeb\SwaggerBundle\Document\SwaggerDocument')
43
            ->disableOriginalConstructor()
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 = [
88
            '/a'     => ['get' => []],
89
            '/a/b'   => ['get' => [], 'post' => []],
90
            '/a/b/c' => ['put' => []],
91
        ];
92
93
        $this->documentMock
94
            ->expects($this->exactly(2))
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->once())
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 = [
138
            '/a' => ['get' => [], 'post' => []],
139
            '/b' => ['get' => []],
140
        ];
141
142
        $this->documentMock
143
            ->expects($this->once())
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 = [
158
            '/a'     => ['get' => []],
159
            '/a/b'   => ['get' => []],
160
            '/a/b/c' => ['get' => []],
161
        ];
162
163
        $this->documentMock
164
            ->expects($this->once())
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
    public function canUseDiKeyAsOperationId()
177
    {
178
        $expected = 'my.controller.key:methodName';
179
        $pathDefinitions = [
180
            '/a' => [
181
                'get'  => [],
182
                'post' => [
183
                    'operationId' => $expected
184
                ]
185
            ],
186
            '/b' => ['get' => []],
187
        ];
188
189
        $this->documentMock
190
            ->expects($this->any())
191
            ->method('getPathDefinitions')
192
            ->willReturn($pathDefinitions);
193
194
        $routes = $this->loader->load(self::DOCUMENT_PATH);
195
196
        $actual = $routes->get('swagger.path.a.my.controller.key:methodName');
197
        $this->assertNotNull($actual);
198
        $this->assertSame($expected, $actual->getDefault('_controller'));
199
    }
200
201
    /**
202
     * @test
203
     */
204 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...
205
    {
206
        $pathDefinitions = [
207
            '/a'     => ['get' => []],
208
            '/a/b'   => ['get' => [], 'post' => []],
209
            '/a/b/c' => ['put' => []],
210
        ];
211
212
        $this->documentMock
213
            ->expects($this->once())
214
            ->method('getPathDefinitions')
215
            ->willReturn($pathDefinitions);
216
217
        $routes = $this->loader->load(self::DOCUMENT_PATH);
218
219
        $this->assertCount(4, $routes);
220
    }
221
222
    /**
223
     * @test
224
     */
225
    public function routeCollectionWillContainPathFromSwaggerDoc()
226
    {
227
        $pathDefinitions = [
228
            '/a'                => ['get' => []],
229
            '/a/b'              => ['get' => []],
230
            '/a/b/c'            => ['get' => []],
231
            '/d/f/g'            => ['get' => []],
232
            '/1/2/3'            => ['get' => []],
233
            '/foo/{bar}/{blah}' => ['get' => []],
234
            '/z'                => ['get' => []],
235
        ];
236
237
        $this->documentMock
238
            ->expects($this->once())
239
            ->method('getPathDefinitions')
240
            ->willReturn($pathDefinitions);
241
242
        $routes = $this->loader->load(self::DOCUMENT_PATH);
243
244
        $definitionPaths = array_keys($pathDefinitions);
245
        sort($definitionPaths);
246
        $routePaths = array_map(function ($route) {
247
            return $route->getPath();
248
        }, $routes->getIterator()->getArrayCopy());
249
        sort($routePaths);
250
        $this->assertSame($definitionPaths, $routePaths);
251
    }
252
253
    /**
254
     * @test
255
     */
256
    public function willAddRequirementsForIntegerPathParams()
257
    {
258
        $pathDefinitions = [
259
            '/a' => [
260
                'get' => [
261
                    'parameters' => [
262
                        ['name' => 'foo', 'in' => 'path', 'type' => 'integer']
263
                    ]
264
                ]
265
            ],
266
        ];
267
268
        $this->documentMock
269
            ->expects($this->once())
270
            ->method('getPathDefinitions')
271
            ->willReturn($pathDefinitions);
272
273
        $this->documentMock
274
            ->expects($this->once())
275
            ->method('getOperationDefinition')
276
            ->with('/a', 'get')
277
            ->willReturn($pathDefinitions['/a']['get']);
278
279
        $routes = $this->loader->load(self::DOCUMENT_PATH);
280
        $actual = $routes->get('swagger.path.a.get');
281
        $this->assertNotNull($actual);
282
        $requirements = $actual->getRequirements();
283
        $this->assertNotNull($requirements);
284
285
        $this->assertSame($requirements['foo'], '\d+');
286
    }
287
288
    /**
289
     * @test
290
     */
291
    public function willAddRequirementsForStringPatternParams()
292
    {
293
        $expected = '\d{2}hello';
294
        $pathDefinitions = [
295
            '/a' => [
296
                'get' => [
297
                    'parameters' => [
298
                        ['name' => 'aString', 'in' => 'path', 'type' => 'string', 'pattern' => $expected]
299
                    ]
300
                ]
301
            ],
302
        ];
303
304
        $this->documentMock
305
            ->expects($this->once())
306
            ->method('getPathDefinitions')
307
            ->willReturn($pathDefinitions);
308
309
        $this->documentMock
310
            ->expects($this->once())
311
            ->method('getOperationDefinition')
312
            ->with('/a', 'get')
313
            ->willReturn($pathDefinitions['/a']['get']);
314
315
        $routes = $this->loader->load(self::DOCUMENT_PATH);
316
        $actual = $routes->get('swagger.path.a.get');
317
        $this->assertNotNull($actual);
318
        $requirements = $actual->getRequirements();
319
        $this->assertNotNull($requirements);
320
321
        $this->assertSame($expected, $requirements['aString']);
322
    }
323
324
    /**
325
     * @test
326
     */
327
    public function willAddRequirementsForStringEnumParams()
328
    {
329
        $enum = ['a', 'b', 'c'];
330
        $expected = '(a|b|c)';
331
        $pathDefinitions = [
332
            '/a' => [
333
                'get' => [
334
                    'parameters' => [
335
                        ['name' => 'aString', 'in' => 'path', 'type' => 'string', 'enum' => $enum]
336
                    ]
337
                ]
338
            ],
339
        ];
340
341
        $this->documentMock
342
            ->expects($this->once())
343
            ->method('getPathDefinitions')
344
            ->willReturn($pathDefinitions);
345
346
        $this->documentMock
347
            ->expects($this->once())
348
            ->method('getOperationDefinition')
349
            ->with('/a', 'get')
350
            ->willReturn($pathDefinitions['/a']['get']);
351
352
        $routes = $this->loader->load(self::DOCUMENT_PATH);
353
        $actual = $routes->get('swagger.path.a.get');
354
        $this->assertNotNull($actual);
355
        $requirements = $actual->getRequirements();
356
        $this->assertNotNull($requirements);
357
358
        $this->assertSame($expected, $requirements['aString']);
359
    }
360
}
361