Passed
Pull Request — master (#23)
by
unknown
12:28
created

UrlGeneratorTest::testAbsoluteUrlWithHostInRoute()   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
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 8
rs 10
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
     * If there's host specified in route, it should be used unless there's host parameter in generateAbsolute()
251
     */
252
    public function testAbsoluteUrlWithHostInRoute(): void
253
    {
254
        $routes = [
255
            Route::get('/home/index')->name('index')->host('http://test.com'),
256
        ];
257
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index');
258
259
        $this->assertEquals('http://test.com/home/index', $url);
260
    }
261
262
    /**
263
     * Trailing slash in route host should not break URL generated
264
     */
265
    public function testAbsoluteUrlWithTrailingSlashHostInRoute(): void
266
    {
267
        $routes = [
268
            Route::get('/home/index')->name('index')->host('http://test.com/'),
269
        ];
270
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index');
271
272
        $this->assertEquals('http://test.com/home/index', $url);
273
    }
274
275
    /**
276
     * Last matched host is used for absolute URL generation in case
277
     * host is not specified in either route or createUrlGenerator()
278
     */
279
    public function testLastMatchedHostUsedForAbsoluteUrl(): void
280
    {
281
        $request = new ServerRequest('GET', 'http://test.com/home/index');
282
        $routes = [
283
            Route::get('/home/index')->name('index'),
284
        ];
285
286
        $router = $this->createRouter($routes);
287
        $router->match($request);
288
        $url = $router->generateAbsolute('index');
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

288
        /** @scrutinizer ignore-call */ 
289
        $url = $router->generateAbsolute('index');

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...
289
290
        $this->assertEquals('http://test.com/home/index', $url);
291
    }
292
293
    /**
294
     * If there's non-standard port used in last matched host,
295
     * it should end up in the URL generated
296
     */
297
    public function testLastMatchedHostWithPortUsedForAbsoluteUrl(): void
298
    {
299
        $request = new ServerRequest('GET', 'http://test.com:8080/home/index');
300
        $routes = [
301
            Route::get('/home/index')->name('index'),
302
        ];
303
304
        $router = $this->createRouter($routes);
305
        $router->match($request);
306
        $url = $router->generateAbsolute('index');
307
308
        $this->assertEquals('http://test.com:8080/home/index', $url);
309
    }
310
311
    public function testHostInRouteWithProtocolRelativeSchemeAbsoluteUrl(): void
312
    {
313
        $request = new ServerRequest('GET', 'http://test.com/home/index');
314
        $routes = [
315
            Route::get('/home/index')->name('index')->host('//test.com'),
316
        ];
317
318
        $router = $this->createRouter($routes);
319
        $router->match($request);
320
        $url = $router->generateAbsolute('index');
321
322
        $this->assertEquals('//test.com/home/index', $url);
323
    }
324
325
    public function testHostInMethodWithProtocolRelativeSchemeAbsoluteUrl(): void
326
    {
327
        $request = new ServerRequest('GET', 'http://test.com/home/index');
328
        $routes = [
329
            Route::get('/home/index')->name('index')->host('//mysite.com'),
330
        ];
331
332
        $router = $this->createRouter($routes);
333
        $router->match($request);
334
        $url = $router->generateAbsolute('index', [], null, '//test.com');
335
336
        $this->assertEquals('//test.com/home/index', $url);
337
    }
338
339
    public function testHostInRouteProtocolRelativeSchemeAbsoluteUrl(): void
340
    {
341
        $request = new ServerRequest('GET', 'http://test.com/home/index');
342
        $routes = [
343
            Route::get('/home/index')->name('index')->host('http://test.com'),
344
            Route::get('/home/view')->name('view')->host('test.com'),
345
        ];
346
347
        $router = $this->createRouter($routes);
348
        $router->match($request);
349
        $url1 = $router->generateAbsolute('index', [], '');
350
        $url2 = $router->generateAbsolute('view', [], '');
351
352
        $this->assertEquals('//test.com/home/index', $url1);
353
        $this->assertEquals('//test.com/home/view', $url2);
354
    }
355
356
    public function testHostInMethodProtocolRelativeSchemeAbsoluteUrl(): void
357
    {
358
        $request = new ServerRequest('GET', 'http://test.com/home/index');
359
        $routes = [
360
            Route::get('/home/index')->name('index')->host('//mysite.com'),
361
        ];
362
363
        $router = $this->createRouter($routes);
364
        $router->match($request);
365
        $url1 = $router->generateAbsolute('index', [], '', 'http://test.com');
366
        $url2 = $router->generateAbsolute('index', [], '', 'test.com');
367
368
        $this->assertEquals('//test.com/home/index', $url1);
369
        $this->assertEquals('//test.com/home/index', $url2);
370
    }
371
}
372