Passed
Pull Request — master (#23)
by Alexander
01:28
created

testAbsoluteUrlHostOverrideWithTrailingSlash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
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 testAbsoluteUrlSchemeOverride(): 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
     * If there's host specified in route, it should be used unless there's host parameter in generateAbsolute()
238
     */
239
    public function testAbsoluteUrlWithHostInRoute(): void
240
    {
241
        $routes = [
242
            Route::get('/home/index')->name('index')->host('http://test.com'),
243
        ];
244
        $url = $this->createUrlGenerator($routes)->generateAbsolute('index');
245
246
        $this->assertEquals('http://test.com/home/index', $url);
247
    }
248
249
    /**
250
     * Trailing slash in route host should not break URL generated
251
     */
252
    public function testAbsoluteUrlWithTrailingSlashHostInRoute(): 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
     * Last matched host is used for absolute URL generation in case
264
     * host is not specified in either route or createUrlGenerator()
265
     */
266
    public function testLastMatchedHostUsedForAbsoluteUrl(): void
267
    {
268
        $request = new ServerRequest('GET', 'http://test.com/home/index');
269
        $routes = [
270
            Route::get('/home/index')->name('index'),
271
        ];
272
273
        $router = $this->createUrlGenerator($routes);
274
        $router->match($request);
275
        $url = $router->generateAbsolute('index');
276
277
        $this->assertEquals('http://test.com/home/index', $url);
278
    }
279
280
    /**
281
     * If there's non-standard port used in last matched host,
282
     * it should end up in the URL generated
283
     */
284
    public function testLastMatchedHostWithPortUsedForAbsoluteUrl(): void
285
    {
286
        $request = new ServerRequest('GET', 'http://test.com:8080/home/index');
287
        $routes = [
288
            Route::get('/home/index')->name('index'),
289
        ];
290
291
        $router = $this->createRouter($routes);
292
        $router->match($request);
293
        $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

293
        /** @scrutinizer ignore-call */ 
294
        $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...
294
295
        $this->assertEquals('http://test.com:8080/home/index', $url);
296
    }
297
298
    public function testAbsoluteUrlFromUrlHostParamWithProtocolRelativeSchemeGenerated(): void
299
    {
300
        $request = new ServerRequest('GET', 'http://test.com/home/index');
301
        $routes = [
302
            Route::get('/home/index')->name('index')->host('//test.com'),
303
        ];
304
305
        $router = $this->createRouter($routes);
306
        $router->match($request);
307
        $url = $router->generateAbsolute('index');
308
309
        $this->assertEquals('http://test.com/home/index', $url);
310
    }
311
312
    public function testAbsoluteUrlFromMethodHostParamWithProtocolRelativeSchemeGenerated(): void
313
    {
314
        $request = new ServerRequest('GET', 'http://test.com/home/index');
315
        $routes = [
316
            Route::get('/home/index')->name('index')->host('//mysite.com'),
317
        ];
318
319
        $router = $this->createRouter($routes);
320
        $router->match($request);
321
        $url = $router->generateAbsolute('index', [], null, '//test.com');
322
323
        $this->assertEquals('http://test.com/home/index', $url);
324
    }
325
}
326