Passed
Pull Request — master (#23)
by
unknown
01:22
created

UrlGeneratorTest::testSimpleRouteGenerated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Yiisoft\Router\FastRoute\Tests;
4
5
use Nyholm\Psr7\ServerRequest;
6
use PHPUnit\Framework\TestCase;
7
use Yiisoft\Router\Group;
8
use Yiisoft\Router\Route;
9
use Yiisoft\Router\RouteNotFoundException;
10
use Yiisoft\Router\RouterInterface;
11
use Yiisoft\Router\UrlGeneratorInterface;
12
13
final class UrlGeneratorTest extends TestCase
14
{
15
    private function createUrlGenerator(array $routes): UrlGeneratorInterface
16
    {
17
        $container = new DummyContainer();
18
        $factory = new RouteFactory();
19
20
        return $factory($routes, $container);
21
    }
22
23
    private function createRouter(array $routes): RouterInterface
24
    {
25
        $container = new DummyContainer();
26
        $factory = new RouteFactory();
27
28
        return $factory($routes, $container);
29
    }
30
31
    public function testSimpleRouteGenerated(): void
32
    {
33
        $routes = [
34
            Route::get('/home/index')->name('index'),
35
        ];
36
        $url = $this->createUrlGenerator($routes)->generate('index');
37
38
        $this->assertEquals('/home/index', $url);
39
    }
40
41
    public function testRouteWithoutNameNotFound(): void
42
    {
43
        $routes = [
44
            Route::get('/home/index'),
45
            Route::get('/index'),
46
            Route::get('index'),
47
        ];
48
        $urlGenerator = $this->createUrlGenerator($routes);
49
50
        $this->expectException(RouteNotFoundException::class);
51
        $urlGenerator->generate('index');
52
    }
53
54
    public function testParametersSubstituted(): void
55
    {
56
        $routes = [
57
            Route::get('/view/{id:\d+}/{text:~[\w]+}#{tag:\w+}')->name('view'),
58
        ];
59
        $url = $this->createUrlGenerator($routes)->generate('view', ['id' => 100, 'tag' => 'yii', 'text' => '~test']);
60
61
        $this->assertEquals('/view/100/~test#yii', $url);
62
    }
63
64
    public function testExceptionThrownIfParameterPatternDoesntMatch(): void
65
    {
66
        $routes = [
67
            Route::get('/view/{id:\w+}')->name('view'),
68
        ];
69
        $urlGenerator = $this->createUrlGenerator($routes);
70
71
        $this->expectExceptionMessage('Parameter value for [id] did not match the regex `\w+`');
72
        $urlGenerator->generate('view', ['id' => null]);
73
    }
74
75
    public function testExceptionThrownIfAnyParameterIsMissing(): void
76
    {
77
        $routes = [
78
            Route::get('/view/{id:\d+}/{value}')->name('view'),
79
        ];
80
        $urlGenerator = $this->createUrlGenerator($routes);
81
82
        $this->expectExceptionMessage('Route `view` expects at least parameter values for [id,value], but received [id]');
83
        $urlGenerator->generate('view', ['id' => 123]);
84
    }
85
86
    public function testGroupPrefixAppended(): void
87
    {
88
        $routes = [
89
            Group::create('/api', [
90
                Route::get('/post')->name('post/index'),
91
                Route::get('/post/{id}')->name('post/view'),
92
            ]),
93
        ];
94
        $urlGenerator = $this->createUrlGenerator($routes);
95
96
        $url = $urlGenerator->generate('post/index');
97
        $this->assertEquals('/api/post', $url);
98
99
        $url = $urlGenerator->generate('post/view', ['id' => 42]);
100
        $this->assertEquals('/api/post/42', $url);
101
    }
102
103
    public function testNestedGroupsPrefixAppended(): void
104
    {
105
        $routes = [
106
            Group::create('/api', [
107
                Group::create('/v1', [
108
                    Route::get('/user')->name('api-v1-user/index'),
109
                    Route::get('/user/{id}')->name('api-v1-user/view'),
110
                    Group::create('/news', [
111
                        Route::get('/post')->name('api-v1-news-post/index'),
112
                        Route::get('/post/{id}')->name('api-v1-news-post/view'),
113
                    ]),
114
                    Group::create('/blog', [
115
                        Route::get('/post')->name('api-v1-blog-post/index'),
116
                        Route::get('/post/{id}')->name('api-v1-blog-post/view'),
117
                    ]),
118
                    Route::get('/note')->name('api-v1-note/index'),
119
                    Route::get('/note/{id}')->name('api-v1-note/view'),
120
                ])
121
            ])
122
        ];
123
        $urlGenerator = $this->createUrlGenerator($routes);
124
125
        $url = $urlGenerator->generate('api-v1-user/index');
126
        $this->assertEquals('/api/v1/user', $url);
127
128
        $url = $urlGenerator->generate('api-v1-user/view', ['id' => 42]);
129
        $this->assertEquals('/api/v1/user/42', $url);
130
131
        $url = $urlGenerator->generate('api-v1-news-post/index');
132
        $this->assertEquals('/api/v1/news/post', $url);
133
134
        $url = $urlGenerator->generate('api-v1-news-post/view', ['id' => 42]);
135
        $this->assertEquals('/api/v1/news/post/42', $url);
136
137
        $url = $urlGenerator->generate('api-v1-blog-post/index');
138
        $this->assertEquals('/api/v1/blog/post', $url);
139
140
        $url = $urlGenerator->generate('api-v1-blog-post/view', ['id' => 42]);
141
        $this->assertEquals('/api/v1/blog/post/42', $url);
142
143
        $url = $urlGenerator->generate('api-v1-note/index');
144
        $this->assertEquals('/api/v1/note', $url);
145
146
        $url = $urlGenerator->generate('api-v1-note/view', ['id' => 42]);
147
        $this->assertEquals('/api/v1/note/42', $url);
148
    }
149
150
    public function testExtraParametersAddedAsQueryString(): void
151
    {
152
        $routes = [
153
            Route::get('/test/{name}')
154
                ->name('test')
155
        ];
156
157
        $url = $this->createUrlGenerator($routes)->generate('test', ['name' => 'post', 'id' => 12, 'sort' => 'asc']);
158
        $this->assertEquals('/test/post?id=12&sort=asc', $url);
159
    }
160
161
    public function testDefaultNotUsedForOptionalParameter(): void
162
    {
163
        $routes = [
164
            Route::get('/[{name}]')
165
                ->name('defaults')
166
                ->defaults(['name' => 'default'])
167
        ];
168
169
        $url = $this->createUrlGenerator($routes)->generate('defaults');
170
        $this->assertEquals('/', $url);
171
    }
172
173
    public function testValueUsedForOptionalParameter(): void
174
    {
175
        $routes = [
176
            Route::get('/[{name}]')
177
                ->name('defaults')
178
                ->defaults(['name' => 'default'])
179
        ];
180
181
        $url = $this->createUrlGenerator($routes)->generate('defaults', ['name' => 'test']);
182
        $this->assertEquals('/test', $url);
183
    }
184
185
    public function testDefaultNotUsedForRequiredParameter(): void
186
    {
187
        $routes = [
188
            Route::get('/{name}')
189
                ->name('defaults')
190
                ->defaults(['name' => 'default'])
191
        ];
192
193
        $this->expectExceptionMessage('Route `defaults` expects at least parameter values for [name], but received []');
194
        $this->createUrlGenerator($routes)->generate('defaults');
195
    }
196
197
    /**
198
     * Host specified in generateAbsolute() should override host specified in route
199
     */
200
    public function testAbsoluteUrlHostHostOverride(): void
201
    {
202
        $routes = [
203
            Route::get('/home/index')->name('index')->host('http://test.com'),
204
        ];
205
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index', [], null, 'http://mysite.com');
0 ignored issues
show
Bug introduced by
The method generateAbsolute() does not exist on Yiisoft\Router\UrlGeneratorInterface. Did you maybe mean generate()? ( Ignorable by Annotation )

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

205
        $url = $this->createUrlGenerator($routes)->/** @scrutinizer ignore-call */ generateAbsolute('index', [], null, 'http://mysite.com');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
206
207
        $this->assertEquals('http://mysite.com/home/index', $url);
208
    }
209
210
    /**
211
     * Trailing slash in host argument of generateAbsolute() should not break URL generated
212
     */
213
    public function testAbsoluteUrlHostOverrideWithTrailingSlash(): void
214
    {
215
        $routes = [
216
            Route::get('/home/index')->name('index')->host('http://test.com'),
217
        ];
218
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index', [], null, 'http://mysite.com/');
219
220
        $this->assertEquals('http://mysite.com/home/index', $url);
221
    }
222
223
    /**
224
     * Scheme specified in generateAbsolute() should override scheme specified in route
225
     */
226
    public function testAbsoluteUrlSchemeOverrideHostInRouteScheme(): void
227
    {
228
        $routes = [
229
            Route::get('/home/index')->name('index')->host('http://test.com'),
230
        ];
231
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index', [], 'https');
232
233
        $this->assertEquals('https://test.com/home/index', $url);
234
    }
235
236
    /**
237
     * Scheme specified in generateAbsolute() should override scheme specified in method
238
     */
239
    public function testAbsoluteUrlSchemeOverrideHostInMethodScheme(): void
240
    {
241
        $routes = [
242
            Route::get('/home/index')->name('index'),
243
        ];
244
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index', [], 'https', 'http://test.com');
245
246
        $this->assertEquals('https://test.com/home/index', $url);
247
    }
248
249
    /**
250
     * Scheme specified in generateAbsolute() should override scheme specified in the matched host
251
     */
252
    public function testAbsoluteUrlSchemeOverrideLastMatchedHostScheme(): void
253
    {
254
        $request = new ServerRequest('GET', 'http://test.com/home/index');
255
        $routes = [
256
            Route::get('/home/index')->name('index'),
257
        ];
258
        $router = $this->createRouter($routes);
259
        $router->match($request);
260
        $url = $router->generateAbsolute('index', [], 'https');
0 ignored issues
show
Bug introduced by
The method generateAbsolute() does not exist on Yiisoft\Router\RouterInterface. Did you maybe mean generate()? ( Ignorable by Annotation )

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

260
        /** @scrutinizer ignore-call */ 
261
        $url = $router->generateAbsolute('index', [], 'https');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
261
262
        $this->assertEquals('https://test.com/home/index', $url);
263
    }
264
265
    /**
266
     * If there's host specified in route, it should be used unless there's host parameter in generateAbsolute()
267
     */
268
    public function testAbsoluteUrlWithHostInRoute(): void
269
    {
270
        $routes = [
271
            Route::get('/home/index')->name('index')->host('http://test.com'),
272
        ];
273
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index');
274
275
        $this->assertEquals('http://test.com/home/index', $url);
276
    }
277
278
    /**
279
     * Trailing slash in route host should not break URL generated
280
     */
281
    public function testAbsoluteUrlWithTrailingSlashHostInRoute(): void
282
    {
283
        $routes = [
284
            Route::get('/home/index')->name('index')->host('http://test.com/'),
285
        ];
286
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index');
287
288
        $this->assertEquals('http://test.com/home/index', $url);
289
    }
290
291
    /**
292
     * Last matched host is used for absolute URL generation in case
293
     * host is not specified in either route or createUrlGenerator()
294
     */
295
    public function testLastMatchedHostUsedForAbsoluteUrl(): void
296
    {
297
        $request = new ServerRequest('GET', 'http://test.com/home/index');
298
        $routes = [
299
            Route::get('/home/index')->name('index'),
300
        ];
301
302
        $router = $this->createRouter($routes);
303
        $router->match($request);
304
        $url = $router->generateAbsolute('index');
305
306
        $this->assertEquals('http://test.com/home/index', $url);
307
    }
308
309
    /**
310
     * If there's non-standard port used in last matched host,
311
     * it should end up in the URL generated
312
     */
313
    public function testLastMatchedHostWithPortUsedForAbsoluteUrl(): void
314
    {
315
        $request = new ServerRequest('GET', 'http://test.com:8080/home/index');
316
        $routes = [
317
            Route::get('/home/index')->name('index'),
318
        ];
319
320
        $router = $this->createRouter($routes);
321
        $router->match($request);
322
        $url = $router->generateAbsolute('index');
323
324
        $this->assertEquals('http://test.com:8080/home/index', $url);
325
    }
326
327
    public function testHostInRouteWithProtocolRelativeSchemeAbsoluteUrl(): void
328
    {
329
        $request = new ServerRequest('GET', 'http://test.com/home/index');
330
        $routes = [
331
            Route::get('/home/index')->name('index')->host('//test.com'),
332
        ];
333
334
        $router = $this->createRouter($routes);
335
        $router->match($request);
336
        $url = $router->generateAbsolute('index');
337
338
        $this->assertEquals('//test.com/home/index', $url);
339
    }
340
341
    public function testHostInMethodWithProtocolRelativeSchemeAbsoluteUrl(): void
342
    {
343
        $request = new ServerRequest('GET', 'http://test.com/home/index');
344
        $routes = [
345
            Route::get('/home/index')->name('index')->host('//mysite.com'),
346
        ];
347
348
        $router = $this->createRouter($routes);
349
        $router->match($request);
350
        $url = $router->generateAbsolute('index', [], null, '//test.com');
351
352
        $this->assertEquals('//test.com/home/index', $url);
353
    }
354
355
    public function testHostInRouteProtocolRelativeSchemeAbsoluteUrl(): void
356
    {
357
        $request = new ServerRequest('GET', 'http://test.com/home/index');
358
        $routes = [
359
            Route::get('/home/index')->name('index')->host('http://test.com'),
360
            Route::get('/home/view')->name('view')->host('test.com'),
361
        ];
362
363
        $router = $this->createRouter($routes);
364
        $router->match($request);
365
        $url1 = $router->generateAbsolute('index', [], '');
366
        $url2 = $router->generateAbsolute('view', [], '');
367
368
        $this->assertEquals('//test.com/home/index', $url1);
369
        $this->assertEquals('//test.com/home/view', $url2);
370
    }
371
372
    public function testHostInMethodProtocolRelativeSchemeAbsoluteUrl(): void
373
    {
374
        $request = new ServerRequest('GET', 'http://test.com/home/index');
375
        $routes = [
376
            Route::get('/home/index')->name('index')->host('//mysite.com'),
377
        ];
378
379
        $router = $this->createRouter($routes);
380
        $router->match($request);
381
        $url1 = $router->generateAbsolute('index', [], '', 'http://test.com');
382
        $url2 = $router->generateAbsolute('index', [], '', 'test.com');
383
384
        $this->assertEquals('//test.com/home/index', $url1);
385
        $this->assertEquals('//test.com/home/index', $url2);
386
    }
387
388
    public function testLastMatchedHostProtocolRelativeSchemeAbsoluteUrl(): void
389
    {
390
        $request = new ServerRequest('GET', 'http://test.com/home/index');
391
        $routes = [
392
            Route::get('/home/index')->name('index'),
393
        ];
394
395
        $router = $this->createRouter($routes);
396
        $router->match($request);
397
        $url = $router->generateAbsolute('index', [], '');
398
399
        $this->assertEquals('//test.com/home/index', $url);
400
    }
401
}
402