Passed
Branch master (6c5a52)
by Ch
02:28
created

RouterTest::testMapWithName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 0
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
20
    /**
21
     * Sets up the fixture, for example, opens a network connection.
22
     * This method is called before a test is executed.
23
     */
24
    protected function setUp()
25
    {
26
        $parser = new RouterParser();
27
        $this->router  = new Router($parser, [], '', []);
28
        $this->closure = function () {
29
        };
30
    }
31
32
    /**
33
     * @covers Router::getRoutes
34
     */
35
    public function testMapAndGetRoutes()
36
    {
37
        $route = ['POST', '/[:controller]/[:action]', $this->closure, null];
38
39
        call_user_func_array([$this->router, 'map'], $route);
40
41
        $routes = $this->router->getRoutes();
42
43
        $this->assertInternalType('array', $routes);
44
        $this->assertEquals([$route], $routes);
45
    }
46
47
    /**
48
     * @covers Router::setRoutes
49
     */
50
    public function testAddRoutesWithArrayArgument()
51
    {
52
        $route1 = ['POST', '/[:controller]/[:action]', $this->closure, null];
53
        $route2 = ['POST', '/[:controller]/[:action]', $this->closure, 'second_route'];
54
55
        $this->router->setRoutes([$route1, $route2]);
56
        
57
        $routes = $this->router->getRoutes();
58
        
59
        $this->assertEquals($route1, $routes[0]);
60
        $this->assertEquals($route2, $routes[1]);
61
    }
62
63
    /**
64
     * @covers Router::setRoutes
65
     */
66
    public function testAddRoutesWithTraversableArgument()
67
    {
68
        $traversable = new SimpleTraversable();
69
        $this->router->setRoutes($traversable);
70
        
71
        $traversable->rewind();
72
        
73
        $first = $traversable->current();
74
        $traversable->next();
75
        $second = $traversable->current();
76
        
77
        $routes = $this->router->getRoutes();
78
        
79
        $this->assertEquals($first, $routes[0]);
80
        $this->assertEquals($second, $routes[1]);
81
    }
82
83
    /**
84
     * @covers Router::setRoutes
85
     */
86
    public function testAddRoutesWidthInvalidArgument()
87
    {
88
        try {
89
            $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

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

207
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/users/1/delete', 'GET'));
Loading history...
208
        $this->assertFalse($this->router->match('/users/abc/delete', 'POST'));
209
        $this->assertFalse($this->router->match('/users/1/create', 'GET'));
210
    }
211
    
212 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...
213
    {
214
        $this->router->map('GET', '/foo/[:controller]/[:action]', 'foo_action', 'foo_route');
215
        
216
        $this->router->setServer([
217
            'REQUEST_URI' => '/foo/test/do',
218
            'REQUEST_METHOD' => 'GET'
219
        ]);
220
        
221
        $this->assertEquals(array(
222
            'target' => 'foo_action',
223
            'params' => array(
224
                'controller' => 'test',
225
                'action' => 'do'
226
            ),
227
            'name' => 'foo_route'
228
        ), $this->router->match());
229
    }
230
    
231 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...
232
    {
233
        $this->router->map('GET', '/bar/[:controller]/[:action].[:type]?', 'bar_action', 'bar_route');
234
        
235
        $this->assertEquals(array(
236
            'target' => 'bar_action',
237
            'params' => array(
238
                'controller' => 'test',
239
                'action' => 'do',
240
                'type' => 'json'
241
            ),
242
            'name' => 'bar_route'
243
        ), $this->router->match('/bar/test/do.json', 'GET'));
244
    }
245
    
246 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...
247
    {
248
        $this->router->map('GET', '/a', 'foo_action', 'foo_route');
249
        $this->router->map('GET', '*', 'bar_action', 'bar_route');
250
        
251
        $this->assertEquals(array(
252
            'target' => 'bar_action',
253
            'params' => array(),
254
            'name' => 'bar_route'
255
        ), $this->router->match('/everything', 'GET'));
256
    }
257
    
258 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...
259
    {
260
        $this->router->map('GET', '@^/[a-z]*$', 'bar_action', 'bar_route');
261
        
262
        $this->assertEquals(array(
263
            'target' => 'bar_action',
264
            'params' => array(),
265
            'name' => 'bar_route'
266
        ), $this->router->match('/everything', 'GET'));
267
        
268
        $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

268
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/some-other-thing', 'GET'));
Loading history...
269
    }
270
271
    public function testMatchWithUnicodeRegex()
272
    {
273
        $pattern = '/(?<path>[^';
274
        // Arabic characters
275
        $pattern .= '\x{0600}-\x{06FF}';
276
        $pattern .= '\x{FB50}-\x{FDFD}';
277
        $pattern .= '\x{FE70}-\x{FEFF}';
278
        $pattern .= '\x{0750}-\x{077F}';
279
        // Alphanumeric, /, _, - and space characters
280
        $pattern .= 'a-zA-Z0-9\/_\-\s';
281
        // 'ZERO WIDTH NON-JOINER'
282
        $pattern .= '\x{200C}';
283
        $pattern .= ']+)';
284
        
285
        $this->router->map('GET', '@' . $pattern, 'unicode_action', 'unicode_route');
286
        
287
        $this->assertEquals(array(
288
            'target' => 'unicode_action',
289
            'name' => 'unicode_route',
290
            'params' => array(
291
                'path' => '大家好'
292
            )
293
        ), $this->router->match('/大家好', 'GET'));
294
        
295
        $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

295
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/﷽‎', 'GET'));
Loading history...
296
    }
297
298
    /**
299
     * @covers Router::setMatchTypes
300
     */
301
    public function testMatchWithCustomNamedRegex()
302
    {
303
        $this->router->getParser()->setMatchTypes(array('cId' => '[a-zA-Z]{2}[0-9](?:_[0-9]++)?'));
304
        $this->router->map('GET', '/bar/[cId:customId]', 'bar_action', 'bar_route');
305
        
306
        $this->assertEquals(array(
307
            'target' => 'bar_action',
308
            'params' => array(
309
                'customId' => 'AB1',
310
            ),
311
            'name' => 'bar_route'
312
        ), $this->router->match('/bar/AB1', 'GET'));
313
314
        $this->assertEquals(array(
315
            'target' => 'bar_action',
316
            'params' => array(
317
                'customId' => 'AB1_0123456789',
318
            ),
319
            'name' => 'bar_route'
320
        ), $this->router->match('/bar/AB1_0123456789', 'GET'));
321
        
322
        $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

322
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/some-other-thing', 'GET'));
Loading history...
323
    }
324
325
    public function testMatchWithCustomNamedUnicodeRegex()
326
    {
327
        $pattern = '[^';
328
        // Arabic characters
329
        $pattern .= '\x{0600}-\x{06FF}';
330
        $pattern .= '\x{FB50}-\x{FDFD}';
331
        $pattern .= '\x{FE70}-\x{FEFF}';
332
        $pattern .= '\x{0750}-\x{077F}';
333
        $pattern .= ']+';
334
        
335
        $this->router->getParser()->setMatchTypes(array('nonArabic' => $pattern));
336
        $this->router->map('GET', '/bar/[nonArabic:string]', 'non_arabic_action', 'non_arabic_route');
337
338
        $this->assertEquals(array(
339
            'target' => 'non_arabic_action',
340
            'name'   => 'non_arabic_route',
341
            'params' => array(
342
                'string' => 'some-path'
343
            )
344
        ), $this->router->match('/bar/some-path', 'GET'));
345
        
346
        $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

346
        $this->assertFalse(/** @scrutinizer ignore-type */ $this->router->match('/﷽‎', 'GET'));
Loading history...
347
    }
348
}
349