1<?php 2/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ 3 4namespace Tests\Icinga\Web; 5 6use Mockery; 7use Icinga\Web\Url; 8use Icinga\Test\BaseTestCase; 9 10class UrlTest extends BaseTestCase 11{ 12 public function testWhetherFromPathCutsOfTheFirstCharOfThePathIfUrlIsInternalAndHasAUsernameInIt() 13 { 14 $this->getRequestMock()->shouldReceive('getServer')->with("SERVER_NAME")->andReturn('localhost') 15 ->shouldReceive('getServer')->with("SERVER_PORT")->andReturn('8080'); 16 17 $url = Url::fromPath('http://testusername:testpassword@localhost:8080/path/to/my/url.html'); 18 $this->assertEquals( 19 'path/to/my/url.html', 20 $url->getPath(), 21 'Url::fromPath does not cut of the first char of path if the url is internal and has a username in it' 22 ); 23 } 24 25 public function testWhetherGetAbsoluteUrlReturnsTheBasePathIfUrlIsInternalAndHasAUsernameInIt() 26 { 27 $this->getRequestMock()->shouldReceive('getServer')->with("SERVER_NAME")->andReturn('localhost') 28 ->shouldReceive('getServer')->with("SERVER_PORT")->andReturn('8080'); 29 30 $url = Url::fromPath('http://testusername:testpassword@localhost:8080/path/to/my/url.html'); 31 $this->assertEquals( 32 'http://testusername:testpassword@localhost:8080/path/to/my/url.html', 33 $url->getAbsoluteUrl(), 34 'Url::getAbsoluteUrl does not reassemble the correct basePath' 35 ); 36 } 37 38 public function testWhetherGetAbsoluteUrlReturnsTheBasePathIfUrlIsInternalAndHasNoUsernameInIt() 39 { 40 $url = Url::fromPath('/path/to/my/url.html'); 41 $this->assertEquals( 42 '/path/to/my/url.html', 43 $url->getAbsoluteUrl(), 44 'Url::getAbsoluteUrl does not reassemble the correct basePath' 45 ); 46 } 47 48 public function testWhetherGetAbsoluteUrlReturnsTheBasePathIfUrlIsExternalAndHasAUsernameInIt() 49 { 50 $this->getRequestMock()->shouldReceive('getServer')->with("SERVER_NAME")->andReturn('localhost') 51 ->shouldReceive('getServer')->with("SERVER_PORT")->andReturn('8080'); 52 53 $url = Url::fromPath('http://testusername:testpassword@testhost/path/to/my/url.html'); 54 $this->assertEquals( 55 'http://testusername:testpassword@testhost/path/to/my/url.html', 56 $url->getAbsoluteUrl(), 57 'Url::getAbsoluteUrl does not reassemble the correct basePath' 58 ); 59 } 60 61 public function testWhetherGetAbsoluteUrlReturnsTheBasePathIfUrlIsExternalAndHasNoUsernameInIt() 62 { 63 $this->getRequestMock()->shouldReceive('getServer')->with("SERVER_NAME")->andReturn('localhost') 64 ->shouldReceive('getServer')->with("SERVER_PORT")->andReturn('8080'); 65 66 $url = Url::fromPath('http://testhost/path/to/my/url.html'); 67 $this->assertEquals( 68 'http://testhost/path/to/my/url.html', 69 $url->getAbsoluteUrl(), 70 'Url::getAbsoluteUrl does not reassemble the correct basePath' 71 ); 72 } 73 74 public function testWhetherGetAbsoluteUrlReturnsTheGivenUsernameAndPassword() 75 { 76 $url = Url::fromPath('http://testusername:testpassword@testsite.com/path/to/my/url.html'); 77 $this->assertEquals( 78 'http://testusername:testpassword@testsite.com/path/to/my/url.html', 79 $url->getAbsoluteUrl(), 80 'Url::fromPath does not reassemble the correct url' 81 ); 82 } 83 84 public function testWhetherFromRequestWorksWithoutARequest() 85 { 86 $this->getRequestMock()->shouldReceive('getBaseUrl')->andReturn('/path/to') 87 ->shouldReceive('getPathInfo')->andReturn('my/test/url.html') 88 ->shouldReceive('getQuery')->andReturn(array('param1' => 'value1', 'param2' => 'value2')); 89 90 $url = Url::fromRequest(); 91 $this->assertEquals( 92 '/path/to/my/test/url.html?param1=value1&param2=value2', 93 $url->getAbsoluteUrl('&'), 94 'Url::fromRequest does not reassemble the correct url from the global request' 95 ); 96 } 97 98 public function testWhetherFromRequestWorksWithARequest() 99 { 100 $request = Mockery::mock('Icinga\Web\Request'); 101 $request->shouldReceive('getPathInfo')->andReturn('my/test/url.html') 102 ->shouldReceive('getBaseUrl')->andReturn('/path/to') 103 ->shouldReceive('getQuery')->andReturn(array()); 104 105 $url = Url::fromRequest(array(), $request); 106 $this->assertEquals( 107 '/path/to/my/test/url.html', 108 $url->getAbsoluteUrl(), 109 'Url::fromRequest does not reassemble the correct url from a given request' 110 ); 111 } 112 113 public function testWhetherFromRequestAcceptsAdditionalParameters() 114 { 115 $request = Mockery::mock('Icinga\Web\Request'); 116 $request->shouldReceive('getPathInfo')->andReturn('') 117 ->shouldReceive('getBaseUrl')->andReturn('/') 118 ->shouldReceive('getQuery')->andReturn(array('key1' => 'val1')); 119 120 $url = Url::fromRequest(array('key1' => 'newval1', 'key2' => 'val2'), $request); 121 $this->assertEquals( 122 'val2', 123 $url->getParam('key2', 'wrongval'), 124 'Url::fromRequest does not accept additional parameters' 125 ); 126 $this->assertEquals( 127 'newval1', 128 $url->getParam('key1', 'wrongval1'), 129 'Url::fromRequest does not overwrite existing parameters with additional ones' 130 ); 131 } 132 133 public function testWhetherFromPathProperlyHandlesInvalidUrls() 134 { 135 $this->expectException(\Icinga\Exception\ProgrammingError::class); 136 137 Url::fromPath(null); 138 } 139 140 public function testWhetherFromPathAcceptsAdditionalParameters() 141 { 142 $url = Url::fromPath('/my/test/url.html', array('key' => 'value')); 143 144 $this->assertEquals( 145 'value', 146 $url->getParam('key', 'wrongvalue'), 147 'Url::fromPath does not accept additional parameters' 148 ); 149 } 150 151 public function testWhetherFromPathProperlyParsesUrlsWithoutQuery() 152 { 153 $url = Url::fromPath('/my/test/url.html'); 154 155 $this->assertEquals( 156 '', 157 $url->getBasePath(), 158 'Url::fromPath does not recognize the correct base path' 159 ); 160 $this->assertEquals( 161 '/my/test/url.html', 162 $url->getAbsoluteUrl(), 163 'Url::fromPath does not recognize the correct url path' 164 ); 165 } 166 167 /** 168 * @depends testWhetherFromPathProperlyParsesUrlsWithoutQuery 169 */ 170 public function testWhetherFromPathProperlyRecognizesTheBaseUrl() 171 { 172 $url = Url::fromPath( 173 '/path/to/my/test/url.html', 174 array(), 175 Mockery::mock(array('getBaseUrl' => '/path/to')) 176 ); 177 178 $this->assertEquals( 179 '/path/to/my/test/url.html', 180 $url->getAbsoluteUrl(), 181 'Url::fromPath does not properly differentiate between the base url and its path' 182 ); 183 } 184 185 /** 186 * @depends testWhetherFromPathProperlyRecognizesTheBaseUrl 187 */ 188 public function testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters() 189 { 190 $url = Url::fromPath('/my/test/url.html?param1=%25arg1¶m2=arg%202' 191 . '¶m3[]=1¶m3[]=2¶m3[]=3¶m4[key1]=val1¶m4[key2]=val2'); 192 193 $this->assertEquals( 194 '%arg1', 195 $url->getParam('param1', 'wrongval'), 196 'Url::fromPath does not properly decode escaped characters in query parameter values' 197 ); 198 $this->assertEquals( 199 'arg 2', 200 $url->getParam('param2', 'wrongval'), 201 'Url::fromPath does not properly decode aliases characters in query parameter values' 202 ); 203 /* 204 // Temporarily disabled, no [] support right now 205 $this->assertEquals( 206 array('1', '2', '3'), 207 $url->getParam('param3'), 208 'Url::fromPath does not properly reassemble query parameter values as sequenced values' 209 ); 210 $this->assertEquals( 211 array('key1' => 'val1', 'key2' => 'val2'), 212 $url->getParam('param4'), 213 'Url::fromPath does not properly reassemble query parameters as associative arrays' 214 ); 215 */ 216 } 217 218 /** 219 * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters 220 */ 221 public function testWhetherGetAbsoluteUrlReturnsTheAbsoluteUrl() 222 { 223 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); 224 225 $this->assertEquals( 226 '/my/test/url.html?param=val¶m2=val2', 227 $url->getAbsoluteUrl(), 228 'Url::getAbsoluteUrl does not return the absolute url' 229 ); 230 } 231 232 public function testWhetherGetRelativeUrlReturnsTheEmptyStringForAbsoluteUrls() 233 { 234 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); 235 236 $this->assertEquals( 237 '', 238 $url->getRelativeUrl(), 239 'Url::getRelativeUrl does not return the empty string for absolute urls' 240 ); 241 } 242 243 /** 244 * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters 245 */ 246 public function testWhetherGetParamReturnsTheCorrectParameter() 247 { 248 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); 249 250 $this->assertEquals( 251 'val', 252 $url->getParam('param', 'wrongval'), 253 'Url::getParam does not return the correct value for an existing parameter' 254 ); 255 $this->assertEquals( 256 'val2', 257 $url->getParam('param2', 'wrongval2'), 258 'Url::getParam does not return the correct value for an existing parameter' 259 ); 260 $this->assertEquals( 261 'nonexisting', 262 $url->getParam('param3', 'nonexisting'), 263 'Url::getParam does not return the default value for a non existing parameter' 264 ); 265 } 266 267 /** 268 * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters 269 */ 270 public function testWhetherRemoveRemovesAGivenSingleParameter() 271 { 272 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); 273 $url->remove('param'); 274 275 $this->assertEquals( 276 'val2', 277 $url->getParam('param2', 'wrongval2'), 278 'Url::remove removes not only the given parameter' 279 ); 280 $this->assertEquals( 281 'rightval', 282 $url->getParam('param', 'rightval'), 283 'Url::remove does not remove the given parameter' 284 ); 285 } 286 287 /** 288 * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters 289 */ 290 public function testWhetherRemoveRemovesAGivenSetOfParameters() 291 { 292 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); 293 $url->remove(array('param', 'param2')); 294 295 $this->assertEquals( 296 'val3', 297 $url->getParam('param3', 'wrongval'), 298 'Url::remove removes not only the given parameters' 299 ); 300 $this->assertEquals( 301 'rightval', 302 $url->getParam('param', 'rightval'), 303 'Url::remove does not remove all given parameters' 304 ); 305 $this->assertEquals( 306 'rightval', 307 $url->getParam('param2', 'rightval'), 308 'Url::remove does not remove all given parameters' 309 ); 310 } 311 312 /** 313 * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters 314 */ 315 public function testWhetherGetUrlWithoutReturnsACopyOfTheUrlWithoutAGivenSetOfParameters() 316 { 317 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); 318 $url2 = $url->getUrlWithout(array('param', 'param2')); 319 320 $this->assertNotSame($url, $url2, 'Url::getUrlWithout does not return a new copy of the url'); 321 $this->assertEquals( 322 array(array('param3', 'val3')), 323 $url2->getParams()->toArray(), 324 'Url::getUrlWithout does not remove a given set of parameters from the url' 325 ); 326 } 327 328 /** 329 * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters 330 */ 331 public function testWhetherAddParamsDoesNotOverwriteExistingParameters() 332 { 333 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); 334 $url->addParams(array('param4' => 'val4', 'param3' => 'newval3')); 335 336 $this->assertEquals( 337 'val4', 338 $url->getParam('param4', 'wrongval'), 339 'Url::addParams does not add new parameters' 340 ); 341 $this->assertEquals( 342 'newval3', 343 $url->getParam('param3', 'wrongval'), 344 'Url::addParams does not overwrite existing existing parameters' 345 ); 346 $this->assertEquals( 347 array('val3', 'newval3'), 348 $url->getParams()->getValues('param3'), 349 'Url::addParams does not overwrite existing existing parameters' 350 ); 351 } 352 353 /** 354 * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters 355 */ 356 public function testWhetherOverwriteParamsOverwritesExistingParameters() 357 { 358 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); 359 $url->overwriteParams(array('param4' => 'val4', 'param3' => 'newval3')); 360 361 $this->assertEquals( 362 'val4', 363 $url->getParam('param4', 'wrongval'), 364 'Url::addParams does not add new parameters' 365 ); 366 $this->assertEquals( 367 'newval3', 368 $url->getParam('param3', 'wrongval'), 369 'Url::addParams does not overwrite existing parameters' 370 ); 371 } 372 373 public function testWhetherEqualUrlMaches() 374 { 375 $url1 = '/whatever/is/here?a=b&c=d'; 376 $url2 = Url::fromPath('whatever/is/here', array('a' => 'b', 'c' => 'd')); 377 $this->assertEquals( 378 true, 379 $url2->matches($url1) 380 ); 381 } 382 383 public function testWhetherDifferentUrlDoesNotMatch() 384 { 385 $url1 = '/whatever/is/here?a=b&d=d'; 386 $url2 = Url::fromPath('whatever/is/here', array('a' => 'b', 'c' => 'd')); 387 $this->assertEquals( 388 false, 389 $url2->matches($url1) 390 ); 391 } 392 393 /** 394 * @depends testWhetherGetAbsoluteUrlReturnsTheAbsoluteUrl 395 */ 396 public function testWhetherToStringConversionReturnsTheAbsoluteUrlForHtmlAttributes() 397 { 398 $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); 399 400 $this->assertEquals( 401 '/my/test/url.html?param=val&param2=val2&param3=val3', 402 (string) $url, 403 'Converting a url to string does not return the absolute url' 404 ); 405 } 406} 407