RouterTest   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 327
Duplicated Lines 21.1 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 23
c 2
b 0
f 0
dl 69
loc 327
rs 10

20 Methods

Rating   Name   Duplication   Size   Complexity  
A testMapWithDuplicatedRouteName() 0 8 2
A testGenerate() 6 6 1
A testMapWithName() 0 14 1
A testAddRoutesWithTraversableArgument() 0 15 1
A testMapAndGetRoutes() 0 10 1
A testAddRoutesWidthInvalidArgument() 0 6 2
A testAddRoutesWithArrayArgument() 0 11 1
A testSetBasePath() 0 4 1
A setUp() 0 7 1
B testMatchWithUnicodeRegex() 0 25 1
A testMatchWithCustomNamedUnicodeRegex() 0 22 1
A testMatchWithWildcard() 10 10 1
A testGenerateWithOptionalUrlParts() 6 6 1
A testGenerateWithNonExistingRoute() 0 6 2
A testMatchWithCustomRegexp() 11 11 1
A testMatchWithOptionalUrlParts() 13 13 1
A testMatchWithCustomNamedRegex() 0 22 1
A testMatchWithServerVars() 17 17 1
A testMatch() 0 13 1
A testMatchWithFixedParamValues() 0 14 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
namespace HakimCh\Http\Tests;
3
4
use Exception;
5
use HakimCh\Http\Router;
6
use HakimCh\Http\RouterException;
7
use HakimCh\Http\RouterParser;
8
use phpDocumentor\Reflection\Types\Boolean;
9
use PHPUnit_Framework_TestCase;
10
use stdClass;
11
12
class RouterTest extends PHPUnit_Framework_TestCase
13
{
14
    /**
15
     * @var Router
16
     */
17
    protected $router;
18
    protected $closure;
19
    protected $param1;
20
    protected $param2;
21
22
    /**
23
     * Sets up the fixture, for example, opens a network connection.
24
     * This method is called before a test is executed.
25
     */
26
    protected function setUp()
27
    {
28
        $parser = new RouterParser();
29
        $this->router  = new Router($parser, [], '', []);
30
        $this->param1  = ['controller' => 'test', 'action' => 'someaction'];
31
        $this->param2  = ['controller' => 'test', 'action' => 'someaction', 'type' => 'json'];
32
        $this->closure = function () {
33
        };
34
    }
35
36
    /**
37
     * @covers Router::getRoutes
38
     */
39
    public function testMapAndGetRoutes()
40
    {
41
        $route = ['POST', '/[:controller]/[:action]', $this->closure, null];
42
43
        call_user_func_array([$this->router, 'map'], $route);
44
45
        $routes = $this->router->getRoutes();
46
47
        $this->assertInternalType('array', $routes);
48
        $this->assertEquals([$route], $routes);
49
    }
50
51
    /**
52
     * @covers Router::setRoutes
53
     */
54
    public function testAddRoutesWithArrayArgument()
55
    {
56
        $route1 = ['POST', '/[:controller]/[:action]', $this->closure, null];
57
        $route2 = ['POST', '/[:controller]/[:action]', $this->closure, 'second_route'];
58
59
        $this->router->setRoutes([$route1, $route2]);
60
        
61
        $routes = $this->router->getRoutes();
62
        
63
        $this->assertEquals($route1, $routes[0]);
64
        $this->assertEquals($route2, $routes[1]);
65
    }
66
67
    /**
68
     * @covers Router::setRoutes
69
     */
70
    public function testAddRoutesWithTraversableArgument()
71
    {
72
        $traversable = new SimpleTraversable();
73
        $this->router->setRoutes($traversable);
74
        
75
        $traversable->rewind();
76
        
77
        $first = $traversable->current();
78
        $traversable->next();
79
        $second = $traversable->current();
80
        
81
        $routes = $this->router->getRoutes();
82
        
83
        $this->assertEquals($first, $routes[0]);
84
        $this->assertEquals($second, $routes[1]);
85
    }
86
87
    /**
88
     * @covers Router::setRoutes
89
     */
90
    public function testAddRoutesWidthInvalidArgument()
91
    {
92
        try {
93
            $this->router->setRoutes(new stdClass);
0 ignored issues
show
Bug introduced by
new stdClass() of type stdClass is incompatible with the type Iterator|array expected by parameter $routes of HakimCh\Http\Router::setRoutes(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

93
            $this->router->setRoutes(/** @scrutinizer ignore-type */ new stdClass);
Loading history...
94
        } catch (RouterException $e) {
95
            $this->assertEquals('Routes should be an array or an instance of Iterator', $e->getMessage());
96
        }
97
    }
98
99
    /**
100
     * @covers Router::setBasePath
101
     */
102
    public function testSetBasePath()
103
    {
104
        $this->router->setBasePath('/some/path');
105
        $this->assertEquals('/some/path', $this->router->getBasePath());
106
    }
107
108
    /**
109
     * @covers Router::map
110
     */
111
    public function testMapWithName()
112
    {
113
        $route = ['POST', '/[:controller]/[:action]', $this->closure, 'my_route'];
114
115
        call_user_func_array([$this->router, 'map'], $route);
116
117
        $routes = $this->router->getRoutes();
118
        $namedRoutes = $this->router->getNamedRoutes();
119
120
        $this->assertInternalType('array', $routes);
121
        $this->assertEquals($route, $routes[0]);
122
123
        $this->assertInternalType('array', $namedRoutes);
124
        $this->assertEquals('/[:controller]/[:action]', $namedRoutes['my_route']);
125
    }
126
127
    /**
128
     * @covers Router::map
129
     */
130
    public function testMapWithDuplicatedRouteName()
131
    {
132
        try {
133
            $route = ['POST', '/[:controller]/[:action]', $this->closure, 'my_route'];
134
            call_user_func_array([$this->router, 'map'], $route);
135
            call_user_func_array([$this->router, 'map'], $route);
136
        } catch (Exception $e) {
137
            $this->assertEquals("Can not redeclare route 'my_route'", $e->getMessage());
138
        }
139
    }
140
141
    /**
142
     * @covers Router::generate
143
     */
144 View Code Duplication
    public function testGenerate()
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...
145
    {
146
        $this->router->map('GET', '/[:controller]/[:action]', $this->closure, 'foo_route');
147
        
148
        $this->assertEquals('/test/someaction', $this->router->generate('foo_route', $this->param1));
149
        $this->assertEquals('/test/someaction', $this->router->generate('foo_route', $this->param2));
150
    }
151
152 View Code Duplication
    public function testGenerateWithOptionalUrlParts()
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...
153
    {
154
        $this->router->map('GET', '/[:controller]/[:action].[:type]?', $this->closure, 'bar_route');
155
        
156
        $this->assertEquals('/test/someaction', $this->router->generate('bar_route', $this->param1));
157
        $this->assertEquals('/test/someaction.json', $this->router->generate('bar_route', $this->param2));
158
    }
159
160
    public function testGenerateWithNonExistingRoute()
161
    {
162
        try {
163
            $this->router->generate('non_existing_route');
164
        } catch (Exception $e) {
165
            $this->assertEquals("Route 'non_existing_route' does not exist.", $e->getMessage());
166
        }
167
    }
168
    
169
    /**
170
     * @covers Router::match
171
     * @covers Router::compileRoute
172
     */
173
    public function testMatch()
174
    {
175
        $params = [
176
            'target' => 'foo_action',
177
            'params' => ['controller' => 'test', 'action' => 'do'],
178
            'name'   => 'foo_route'
179
        ];
180
181
        $this->router->map('GET', '/foo/[:controller]/[:action]', 'foo_action', 'foo_route');
182
        
183
        $this->assertEquals($params, $this->router->match('/foo/test/do', 'GET'));
184
        $this->assertSame(false, $this->router->match('/foo/test/do', 'POST'));
185
        $this->assertEquals($params, $this->router->match('/foo/test/do?param=value', 'GET'));
186
    }
187
    
188
    public function testMatchWithFixedParamValues()
189
    {
190
        $params = [
191
            'target' => 'usersController#doAction',
192
            'params' => ['id' => 1, 'action' => 'delete'],
193
            'name' => 'users_do'
194
        ];
195
196
        $this->router->map('POST', '/users/[i:id]/[delete|update:action]', 'usersController#doAction', 'users_do');
197
        
198
        $this->assertEquals($params, $this->router->match('/users/1/delete', 'POST'));
199
        $this->assertFalse($this->router->match('/users/1/delete', 'GET'));
0 ignored issues
show
Bug introduced by
It seems like $this->router->match('/users/1/delete', 'GET') can also be of type array; however, parameter $condition of PHPUnit_Framework_Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

199
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/users/1/delete', 'GET'));
Loading history...
200
        $this->assertFalse($this->router->match('/users/abc/delete', 'POST'));
201
        $this->assertFalse($this->router->match('/users/1/create', 'GET'));
202
    }
203
    
204 View Code Duplication
    public function testMatchWithServerVars()
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
        $this->router->map('GET', '/foo/[:controller]/[:action]', 'foo_action', 'foo_route');
207
        
208
        $this->router->setServer([
209
            'REQUEST_URI' => '/foo/test/do',
210
            'REQUEST_METHOD' => 'GET'
211
        ]);
212
        
213
        $this->assertEquals(array(
214
            'target' => 'foo_action',
215
            'params' => array(
216
                'controller' => 'test',
217
                'action' => 'do'
218
            ),
219
            'name' => 'foo_route'
220
        ), $this->router->match());
221
    }
222
    
223 View Code Duplication
    public function testMatchWithOptionalUrlParts()
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...
224
    {
225
        $this->router->map('GET', '/bar/[:controller]/[:action].[:type]?', 'bar_action', 'bar_route');
226
        
227
        $this->assertEquals(array(
228
            'target' => 'bar_action',
229
            'params' => array(
230
                'controller' => 'test',
231
                'action' => 'do',
232
                'type' => 'json'
233
            ),
234
            'name' => 'bar_route'
235
        ), $this->router->match('/bar/test/do.json', 'GET'));
236
    }
237
    
238 View Code Duplication
    public function testMatchWithWildcard()
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...
239
    {
240
        $this->router->map('GET', '/a', 'foo_action', 'foo_route');
241
        $this->router->map('GET', '*', 'bar_action', 'bar_route');
242
        
243
        $this->assertEquals(array(
244
            'target' => 'bar_action',
245
            'params' => array(),
246
            'name' => 'bar_route'
247
        ), $this->router->match('/everything', 'GET'));
248
    }
249
    
250 View Code Duplication
    public function testMatchWithCustomRegexp()
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...
251
    {
252
        $this->router->map('GET', '@^/[a-z]*$', 'bar_action', 'bar_route');
253
        
254
        $this->assertEquals(array(
255
            'target' => 'bar_action',
256
            'params' => array(),
257
            'name' => 'bar_route'
258
        ), $this->router->match('/everything', 'GET'));
259
        
260
        $this->assertFalse($this->router->match('/some-other-thing', 'GET'));
0 ignored issues
show
Bug introduced by
It seems like $this->router->match('/some-other-thing', 'GET') can also be of type array; however, parameter $condition of PHPUnit_Framework_Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

260
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/some-other-thing', 'GET'));
Loading history...
261
    }
262
263
    public function testMatchWithUnicodeRegex()
264
    {
265
        $pattern = '/(?<path>[^';
266
        // Arabic characters
267
        $pattern .= '\x{0600}-\x{06FF}';
268
        $pattern .= '\x{FB50}-\x{FDFD}';
269
        $pattern .= '\x{FE70}-\x{FEFF}';
270
        $pattern .= '\x{0750}-\x{077F}';
271
        // Alphanumeric, /, _, - and space characters
272
        $pattern .= 'a-zA-Z0-9\/_\-\s';
273
        // 'ZERO WIDTH NON-JOINER'
274
        $pattern .= '\x{200C}';
275
        $pattern .= ']+)';
276
        
277
        $this->router->map('GET', '@' . $pattern, 'unicode_action', 'unicode_route');
278
        
279
        $this->assertEquals(array(
280
            'target' => 'unicode_action',
281
            'name' => 'unicode_route',
282
            'params' => array(
283
                'path' => '大家好'
284
            )
285
        ), $this->router->match('/大家好', 'GET'));
286
        
287
        $this->assertFalse($this->router->match('/﷽‎', 'GET'));
0 ignored issues
show
Bug introduced by
It seems like $this->router->match('/﷽‎', 'GET') can also be of type array; however, parameter $condition of PHPUnit_Framework_Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

287
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/﷽‎', 'GET'));
Loading history...
288
    }
289
290
    /**
291
     * @covers Router::setMatchTypes
292
     */
293
    public function testMatchWithCustomNamedRegex()
294
    {
295
        $this->router->getParser()->setMatchTypes(array('cId' => '[a-zA-Z]{2}[0-9](?:_[0-9]++)?'));
296
        $this->router->map('GET', '/bar/[cId:customId]', 'bar_action', 'bar_route');
297
        
298
        $this->assertEquals(array(
299
            'target' => 'bar_action',
300
            'params' => array(
301
                'customId' => 'AB1',
302
            ),
303
            'name' => 'bar_route'
304
        ), $this->router->match('/bar/AB1', 'GET'));
305
306
        $this->assertEquals(array(
307
            'target' => 'bar_action',
308
            'params' => array(
309
                'customId' => 'AB1_0123456789',
310
            ),
311
            'name' => 'bar_route'
312
        ), $this->router->match('/bar/AB1_0123456789', 'GET'));
313
        
314
        $this->assertFalse($this->router->match('/some-other-thing', 'GET'));
0 ignored issues
show
Bug introduced by
It seems like $this->router->match('/some-other-thing', 'GET') can also be of type array; however, parameter $condition of PHPUnit_Framework_Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

314
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/some-other-thing', 'GET'));
Loading history...
315
    }
316
317
    public function testMatchWithCustomNamedUnicodeRegex()
318
    {
319
        $pattern = '[^';
320
        // Arabic characters
321
        $pattern .= '\x{0600}-\x{06FF}';
322
        $pattern .= '\x{FB50}-\x{FDFD}';
323
        $pattern .= '\x{FE70}-\x{FEFF}';
324
        $pattern .= '\x{0750}-\x{077F}';
325
        $pattern .= ']+';
326
        
327
        $this->router->getParser()->setMatchTypes(array('nonArabic' => $pattern));
328
        $this->router->map('GET', '/bar/[nonArabic:string]', 'non_arabic_action', 'non_arabic_route');
329
330
        $this->assertEquals(array(
331
            'target' => 'non_arabic_action',
332
            'name'   => 'non_arabic_route',
333
            'params' => array(
334
                'string' => 'some-path'
335
            )
336
        ), $this->router->match('/bar/some-path', 'GET'));
337
        
338
        $this->assertFalse($this->router->match('/﷽‎', 'GET'));
0 ignored issues
show
Bug introduced by
It seems like $this->router->match('/﷽‎', 'GET') can also be of type array; however, parameter $condition of PHPUnit_Framework_Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

338
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/﷽‎', 'GET'));
Loading history...
339
    }
340
}
341