Mercurial > hg > isophonics-drupal-site
comparison core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Tests\Component\Utility; | |
4 | |
5 use Drupal\Component\Utility\UrlHelper; | |
6 use PHPUnit\Framework\TestCase; | |
7 | |
8 /** | |
9 * @group Utility | |
10 * | |
11 * @coversDefaultClass \Drupal\Component\Utility\UrlHelper | |
12 */ | |
13 class UrlHelperTest extends TestCase { | |
14 | |
15 /** | |
16 * Provides test data for testBuildQuery(). | |
17 * | |
18 * @return array | |
19 */ | |
20 public function providerTestBuildQuery() { | |
21 return [ | |
22 [['a' => ' &#//+%20@۞'], 'a=%20%26%23//%2B%2520%40%DB%9E', 'Value was properly encoded.'], | |
23 [[' &#//+%20@۞' => 'a'], '%20%26%23%2F%2F%2B%2520%40%DB%9E=a', 'Key was properly encoded.'], | |
24 [['a' => '1', 'b' => '2', 'c' => '3'], 'a=1&b=2&c=3', 'Multiple values were properly concatenated.'], | |
25 [['a' => ['b' => '2', 'c' => '3'], 'd' => 'foo'], 'a%5Bb%5D=2&a%5Bc%5D=3&d=foo', 'Nested array was properly encoded.'], | |
26 [['foo' => NULL], 'foo', 'Simple parameters are properly added.'], | |
27 ]; | |
28 } | |
29 | |
30 /** | |
31 * Tests query building. | |
32 * | |
33 * @dataProvider providerTestBuildQuery | |
34 * @covers ::buildQuery | |
35 * | |
36 * @param array $query | |
37 * The array of query parameters. | |
38 * @param string $expected | |
39 * The expected query string. | |
40 * @param string $message | |
41 * The assertion message. | |
42 */ | |
43 public function testBuildQuery($query, $expected, $message) { | |
44 $this->assertEquals(UrlHelper::buildQuery($query), $expected, $message); | |
45 } | |
46 | |
47 /** | |
48 * Data provider for testValidAbsolute(). | |
49 * | |
50 * @return array | |
51 */ | |
52 public function providerTestValidAbsoluteData() { | |
53 $urls = [ | |
54 'example.com', | |
55 'www.example.com', | |
56 'ex-ample.com', | |
57 '3xampl3.com', | |
58 'example.com/parenthesis', | |
59 'example.com/index.html#pagetop', | |
60 'example.com:8080', | |
61 'subdomain.example.com', | |
62 'example.com/index.php/node', | |
63 'example.com/index.php/node?param=false', | |
64 'user@www.example.com', | |
65 'user:pass@www.example.com:8080/login.php?do=login&style=%23#pagetop', | |
66 '127.0.0.1', | |
67 'example.org?', | |
68 'john%20doe:secret:foo@example.org/', | |
69 'example.org/~,$\'*;', | |
70 'caf%C3%A9.example.org', | |
71 '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html', | |
72 ]; | |
73 | |
74 return $this->dataEnhanceWithScheme($urls); | |
75 } | |
76 | |
77 /** | |
78 * Tests valid absolute URLs. | |
79 * | |
80 * @dataProvider providerTestValidAbsoluteData | |
81 * @covers ::isValid | |
82 * | |
83 * @param string $url | |
84 * The url to test. | |
85 * @param string $scheme | |
86 * The scheme to test. | |
87 */ | |
88 public function testValidAbsolute($url, $scheme) { | |
89 $test_url = $scheme . '://' . $url; | |
90 $valid_url = UrlHelper::isValid($test_url, TRUE); | |
91 $this->assertTrue($valid_url, $test_url . ' is a valid URL.'); | |
92 } | |
93 | |
94 /** | |
95 * Provides data for testInvalidAbsolute(). | |
96 * | |
97 * @return array | |
98 */ | |
99 public function providerTestInvalidAbsolute() { | |
100 $data = [ | |
101 '', | |
102 'ex!ample.com', | |
103 'ex%ample.com', | |
104 ]; | |
105 return $this->dataEnhanceWithScheme($data); | |
106 } | |
107 | |
108 /** | |
109 * Tests invalid absolute URLs. | |
110 * | |
111 * @dataProvider providerTestInvalidAbsolute | |
112 * @covers ::isValid | |
113 * | |
114 * @param string $url | |
115 * The url to test. | |
116 * @param string $scheme | |
117 * The scheme to test. | |
118 */ | |
119 public function testInvalidAbsolute($url, $scheme) { | |
120 $test_url = $scheme . '://' . $url; | |
121 $valid_url = UrlHelper::isValid($test_url, TRUE); | |
122 $this->assertFalse($valid_url, $test_url . ' is NOT a valid URL.'); | |
123 } | |
124 | |
125 /** | |
126 * Provides data for testValidRelative(). | |
127 * | |
128 * @return array | |
129 */ | |
130 public function providerTestValidRelativeData() { | |
131 $data = [ | |
132 'paren(the)sis', | |
133 'index.html#pagetop', | |
134 'index.php/node', | |
135 'index.php/node?param=false', | |
136 'login.php?do=login&style=%23#pagetop', | |
137 ]; | |
138 | |
139 return $this->dataEnhanceWithPrefix($data); | |
140 } | |
141 | |
142 /** | |
143 * Tests valid relative URLs. | |
144 * | |
145 * @dataProvider providerTestValidRelativeData | |
146 * @covers ::isValid | |
147 * | |
148 * @param string $url | |
149 * The url to test. | |
150 * @param string $prefix | |
151 * The prefix to test. | |
152 */ | |
153 public function testValidRelative($url, $prefix) { | |
154 $test_url = $prefix . $url; | |
155 $valid_url = UrlHelper::isValid($test_url); | |
156 $this->assertTrue($valid_url, $test_url . ' is a valid URL.'); | |
157 } | |
158 | |
159 /** | |
160 * Provides data for testInvalidRelative(). | |
161 * | |
162 * @return array | |
163 */ | |
164 public function providerTestInvalidRelativeData() { | |
165 $data = [ | |
166 'ex^mple', | |
167 'example<>', | |
168 'ex%ample', | |
169 ]; | |
170 return $this->dataEnhanceWithPrefix($data); | |
171 } | |
172 | |
173 /** | |
174 * Tests invalid relative URLs. | |
175 * | |
176 * @dataProvider providerTestInvalidRelativeData | |
177 * @covers ::isValid | |
178 * | |
179 * @param string $url | |
180 * The url to test. | |
181 * @param string $prefix | |
182 * The prefix to test. | |
183 */ | |
184 public function testInvalidRelative($url, $prefix) { | |
185 $test_url = $prefix . $url; | |
186 $valid_url = UrlHelper::isValid($test_url); | |
187 $this->assertFalse($valid_url, $test_url . ' is NOT a valid URL.'); | |
188 } | |
189 | |
190 /** | |
191 * Tests query filtering. | |
192 * | |
193 * @dataProvider providerTestFilterQueryParameters | |
194 * @covers ::filterQueryParameters | |
195 * | |
196 * @param array $query | |
197 * The array of query parameters. | |
198 * @param array $exclude | |
199 * A list of $query array keys to remove. Use "parent[child]" to exclude | |
200 * nested items. | |
201 * @param array $expected | |
202 * An array containing query parameters. | |
203 */ | |
204 public function testFilterQueryParameters($query, $exclude, $expected) { | |
205 $filtered = UrlHelper::filterQueryParameters($query, $exclude); | |
206 $this->assertEquals($expected, $filtered, 'The query was not properly filtered.'); | |
207 } | |
208 | |
209 /** | |
210 * Provides data to self::testFilterQueryParameters(). | |
211 * | |
212 * @return array | |
213 */ | |
214 public static function providerTestFilterQueryParameters() { | |
215 return [ | |
216 // Test without an exclude filter. | |
217 [ | |
218 'query' => ['a' => ['b' => 'c']], | |
219 'exclude' => [], | |
220 'expected' => ['a' => ['b' => 'c']], | |
221 ], | |
222 // Exclude the 'b' element. | |
223 [ | |
224 'query' => ['a' => ['b' => 'c', 'd' => 'e']], | |
225 'exclude' => ['a[b]'], | |
226 'expected' => ['a' => ['d' => 'e']], | |
227 ], | |
228 ]; | |
229 } | |
230 | |
231 /** | |
232 * Tests url parsing. | |
233 * | |
234 * @dataProvider providerTestParse | |
235 * @covers ::parse | |
236 * | |
237 * @param string $url | |
238 * URL to test. | |
239 * @param array $expected | |
240 * Associative array with expected parameters. | |
241 */ | |
242 public function testParse($url, $expected) { | |
243 $parsed = UrlHelper::parse($url); | |
244 $this->assertEquals($expected, $parsed, 'The URL was not properly parsed.'); | |
245 } | |
246 | |
247 /** | |
248 * Provides data for self::testParse(). | |
249 * | |
250 * @return array | |
251 */ | |
252 public static function providerTestParse() { | |
253 return [ | |
254 [ | |
255 'http://www.example.com/my/path', | |
256 [ | |
257 'path' => 'http://www.example.com/my/path', | |
258 'query' => [], | |
259 'fragment' => '', | |
260 ], | |
261 ], | |
262 [ | |
263 'http://www.example.com/my/path?destination=home#footer', | |
264 [ | |
265 'path' => 'http://www.example.com/my/path', | |
266 'query' => [ | |
267 'destination' => 'home', | |
268 ], | |
269 'fragment' => 'footer', | |
270 ], | |
271 ], | |
272 'absolute fragment, no query' => [ | |
273 'http://www.example.com/my/path#footer', | |
274 [ | |
275 'path' => 'http://www.example.com/my/path', | |
276 'query' => [], | |
277 'fragment' => 'footer', | |
278 ], | |
279 ], | |
280 [ | |
281 'http://', | |
282 [ | |
283 'path' => '', | |
284 'query' => [], | |
285 'fragment' => '', | |
286 ], | |
287 ], | |
288 [ | |
289 'https://', | |
290 [ | |
291 'path' => '', | |
292 'query' => [], | |
293 'fragment' => '', | |
294 ], | |
295 ], | |
296 [ | |
297 '/my/path?destination=home#footer', | |
298 [ | |
299 'path' => '/my/path', | |
300 'query' => [ | |
301 'destination' => 'home', | |
302 ], | |
303 'fragment' => 'footer', | |
304 ], | |
305 ], | |
306 'relative fragment, no query' => [ | |
307 '/my/path#footer', | |
308 [ | |
309 'path' => '/my/path', | |
310 'query' => [], | |
311 'fragment' => 'footer', | |
312 ], | |
313 ], | |
314 ]; | |
315 } | |
316 | |
317 /** | |
318 * Tests path encoding. | |
319 * | |
320 * @dataProvider providerTestEncodePath | |
321 * @covers ::encodePath | |
322 * | |
323 * @param string $path | |
324 * A path to encode. | |
325 * @param string $expected | |
326 * The expected encoded path. | |
327 */ | |
328 public function testEncodePath($path, $expected) { | |
329 $encoded = UrlHelper::encodePath($path); | |
330 $this->assertEquals($expected, $encoded); | |
331 } | |
332 | |
333 /** | |
334 * Provides data for self::testEncodePath(). | |
335 * | |
336 * @return array | |
337 */ | |
338 public static function providerTestEncodePath() { | |
339 return [ | |
340 ['unencoded path with spaces', 'unencoded%20path%20with%20spaces'], | |
341 ['slashes/should/be/preserved', 'slashes/should/be/preserved'], | |
342 ]; | |
343 } | |
344 | |
345 /** | |
346 * Tests external versus internal paths. | |
347 * | |
348 * @dataProvider providerTestIsExternal | |
349 * @covers ::isExternal | |
350 * | |
351 * @param string $path | |
352 * URL or path to test. | |
353 * @param bool $expected | |
354 * Expected result. | |
355 */ | |
356 public function testIsExternal($path, $expected) { | |
357 $isExternal = UrlHelper::isExternal($path); | |
358 $this->assertEquals($expected, $isExternal); | |
359 } | |
360 | |
361 /** | |
362 * Provides data for self::testIsExternal(). | |
363 * | |
364 * @return array | |
365 */ | |
366 public static function providerTestIsExternal() { | |
367 return [ | |
368 ['/internal/path', FALSE], | |
369 ['https://example.com/external/path', TRUE], | |
370 ['javascript://fake-external-path', FALSE], | |
371 // External URL without an explicit protocol. | |
372 ['//www.drupal.org/foo/bar?foo=bar&bar=baz&baz#foo', TRUE], | |
373 // Internal URL starting with a slash. | |
374 ['/www.drupal.org', FALSE], | |
375 // Simple external URLs. | |
376 ['http://example.com', TRUE], | |
377 ['https://example.com', TRUE], | |
378 ['http://drupal.org/foo/bar?foo=bar&bar=baz&baz#foo', TRUE], | |
379 ['//drupal.org', TRUE], | |
380 // Some browsers ignore or strip leading control characters. | |
381 ["\x00//www.example.com", TRUE], | |
382 ["\x08//www.example.com", TRUE], | |
383 ["\x1F//www.example.com", TRUE], | |
384 ["\n//www.example.com", TRUE], | |
385 // JSON supports decoding directly from UTF-8 code points. | |
386 [json_decode('"\u00AD"') . "//www.example.com", TRUE], | |
387 [json_decode('"\u200E"') . "//www.example.com", TRUE], | |
388 [json_decode('"\uE0020"') . "//www.example.com", TRUE], | |
389 [json_decode('"\uE000"') . "//www.example.com", TRUE], | |
390 // Backslashes should be normalized to forward. | |
391 ['\\\\example.com', TRUE], | |
392 // Local URLs. | |
393 ['node', FALSE], | |
394 ['/system/ajax', FALSE], | |
395 ['?q=foo:bar', FALSE], | |
396 ['node/edit:me', FALSE], | |
397 ['/drupal.org', FALSE], | |
398 ['<front>', FALSE], | |
399 ]; | |
400 } | |
401 | |
402 /** | |
403 * Tests bad protocol filtering and escaping. | |
404 * | |
405 * @dataProvider providerTestFilterBadProtocol | |
406 * @covers ::setAllowedProtocols | |
407 * @covers ::filterBadProtocol | |
408 * | |
409 * @param string $uri | |
410 * Protocol URI. | |
411 * @param string $expected | |
412 * Expected escaped value. | |
413 * @param array $protocols | |
414 * Protocols to allow. | |
415 */ | |
416 public function testFilterBadProtocol($uri, $expected, $protocols) { | |
417 UrlHelper::setAllowedProtocols($protocols); | |
418 $this->assertEquals($expected, UrlHelper::filterBadProtocol($uri)); | |
419 // Multiple calls to UrlHelper::filterBadProtocol() do not cause double | |
420 // escaping. | |
421 $this->assertEquals($expected, UrlHelper::filterBadProtocol(UrlHelper::filterBadProtocol($uri))); | |
422 } | |
423 | |
424 /** | |
425 * Provides data for self::testTestFilterBadProtocol(). | |
426 * | |
427 * @return array | |
428 */ | |
429 public static function providerTestFilterBadProtocol() { | |
430 return [ | |
431 ['javascript://example.com?foo&bar', '//example.com?foo&bar', ['http', 'https']], | |
432 // Test custom protocols. | |
433 ['http://example.com?foo&bar', '//example.com?foo&bar', ['https']], | |
434 // Valid protocol. | |
435 ['http://example.com?foo&bar', 'http://example.com?foo&bar', ['https', 'http']], | |
436 // Colon not part of the URL scheme. | |
437 ['/test:8888?foo&bar', '/test:8888?foo&bar', ['http']], | |
438 ]; | |
439 } | |
440 | |
441 /** | |
442 * Tests dangerous url protocol filtering. | |
443 * | |
444 * @dataProvider providerTestStripDangerousProtocols | |
445 * @covers ::setAllowedProtocols | |
446 * @covers ::stripDangerousProtocols | |
447 * | |
448 * @param string $uri | |
449 * Protocol URI. | |
450 * @param string $expected | |
451 * Expected escaped value. | |
452 * @param array $protocols | |
453 * Protocols to allow. | |
454 */ | |
455 public function testStripDangerousProtocols($uri, $expected, $protocols) { | |
456 UrlHelper::setAllowedProtocols($protocols); | |
457 $stripped = UrlHelper::stripDangerousProtocols($uri); | |
458 $this->assertEquals($expected, $stripped); | |
459 } | |
460 | |
461 /** | |
462 * Provides data for self::testStripDangerousProtocols(). | |
463 * | |
464 * @return array | |
465 */ | |
466 public static function providerTestStripDangerousProtocols() { | |
467 return [ | |
468 ['javascript://example.com', '//example.com', ['http', 'https']], | |
469 // Test custom protocols. | |
470 ['http://example.com', '//example.com', ['https']], | |
471 // Valid protocol. | |
472 ['http://example.com', 'http://example.com', ['https', 'http']], | |
473 // Colon not part of the URL scheme. | |
474 ['/test:8888', '/test:8888', ['http']], | |
475 ]; | |
476 } | |
477 | |
478 /** | |
479 * Enhances test urls with schemes | |
480 * | |
481 * @param array $urls | |
482 * The list of urls. | |
483 * | |
484 * @return array | |
485 * A list of provider data with schemes. | |
486 */ | |
487 protected function dataEnhanceWithScheme(array $urls) { | |
488 $url_schemes = ['http', 'https', 'ftp']; | |
489 $data = []; | |
490 foreach ($url_schemes as $scheme) { | |
491 foreach ($urls as $url) { | |
492 $data[] = [$url, $scheme]; | |
493 } | |
494 } | |
495 return $data; | |
496 } | |
497 | |
498 /** | |
499 * Enhances test urls with prefixes. | |
500 * | |
501 * @param array $urls | |
502 * The list of urls. | |
503 * | |
504 * @return array | |
505 * A list of provider data with prefixes. | |
506 */ | |
507 protected function dataEnhanceWithPrefix(array $urls) { | |
508 $prefixes = ['', '/']; | |
509 $data = []; | |
510 foreach ($prefixes as $prefix) { | |
511 foreach ($urls as $url) { | |
512 $data[] = [$url, $prefix]; | |
513 } | |
514 } | |
515 return $data; | |
516 } | |
517 | |
518 /** | |
519 * Test detecting external urls that point to local resources. | |
520 * | |
521 * @param string $url | |
522 * The external url to test. | |
523 * @param string $base_url | |
524 * The base url. | |
525 * @param bool $expected | |
526 * TRUE if an external URL points to this installation as determined by the | |
527 * base url. | |
528 * | |
529 * @covers ::externalIsLocal | |
530 * @dataProvider providerTestExternalIsLocal | |
531 */ | |
532 public function testExternalIsLocal($url, $base_url, $expected) { | |
533 $this->assertSame($expected, UrlHelper::externalIsLocal($url, $base_url)); | |
534 } | |
535 | |
536 /** | |
537 * Provider for local external url detection. | |
538 * | |
539 * @see \Drupal\Tests\Component\Utility\UrlHelperTest::testExternalIsLocal() | |
540 */ | |
541 public function providerTestExternalIsLocal() { | |
542 return [ | |
543 // Different mixes of trailing slash. | |
544 ['http://example.com', 'http://example.com', TRUE], | |
545 ['http://example.com/', 'http://example.com', TRUE], | |
546 ['http://example.com', 'http://example.com/', TRUE], | |
547 ['http://example.com/', 'http://example.com/', TRUE], | |
548 // Sub directory of site. | |
549 ['http://example.com/foo', 'http://example.com/', TRUE], | |
550 ['http://example.com/foo/bar', 'http://example.com/foo', TRUE], | |
551 ['http://example.com/foo/bar', 'http://example.com/foo/', TRUE], | |
552 // Different sub-domain. | |
553 ['http://example.com', 'http://www.example.com/', FALSE], | |
554 ['http://example.com/', 'http://www.example.com/', FALSE], | |
555 ['http://example.com/foo', 'http://www.example.com/', FALSE], | |
556 // Different TLD. | |
557 ['http://example.com', 'http://example.ca', FALSE], | |
558 ['http://example.com', 'http://example.ca/', FALSE], | |
559 ['http://example.com/', 'http://example.ca/', FALSE], | |
560 ['http://example.com/foo', 'http://example.ca', FALSE], | |
561 ['http://example.com/foo', 'http://example.ca/', FALSE], | |
562 // Different site path. | |
563 ['http://example.com/foo', 'http://example.com/bar', FALSE], | |
564 ['http://example.com', 'http://example.com/bar', FALSE], | |
565 ['http://example.com/bar', 'http://example.com/bar/', FALSE], | |
566 ]; | |
567 } | |
568 | |
569 /** | |
570 * Test invalid url arguments. | |
571 * | |
572 * @param string $url | |
573 * The url to test. | |
574 * @param string $base_url | |
575 * The base url. | |
576 * | |
577 * @covers ::externalIsLocal | |
578 * @dataProvider providerTestExternalIsLocalInvalid | |
579 */ | |
580 public function testExternalIsLocalInvalid($url, $base_url) { | |
581 $this->setExpectedException(\InvalidArgumentException::class); | |
582 UrlHelper::externalIsLocal($url, $base_url); | |
583 } | |
584 | |
585 /** | |
586 * Provides invalid argument data for local external url detection. | |
587 * | |
588 * @see \Drupal\Tests\Component\Utility\UrlHelperTest::testExternalIsLocalInvalid() | |
589 */ | |
590 public function providerTestExternalIsLocalInvalid() { | |
591 return [ | |
592 ['http://example.com/foo', ''], | |
593 ['http://example.com/foo', 'bar'], | |
594 ['http://example.com/foo', 'http://'], | |
595 // Invalid destination urls. | |
596 ['', 'http://example.com/foo'], | |
597 ['bar', 'http://example.com/foo'], | |
598 ['/bar', 'http://example.com/foo'], | |
599 ['bar/', 'http://example.com/foo'], | |
600 ['http://', 'http://example.com/foo'], | |
601 ]; | |
602 } | |
603 | |
604 } |