From 07da92ee4293ca7165cba6d07d808694eee037da Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 25 Apr 2014 14:25:13 +0200 Subject: [PATCH] Rewrite test for Icinga\Web\Url and fix some bugs refs #6011 --- library/Icinga/Test/BaseTestCase.php | 21 +- library/Icinga/Web/Url.php | 209 +++++----- test/php/library/Icinga/Web/UrlTest.php | 512 ++++++++++++------------ 3 files changed, 394 insertions(+), 348 deletions(-) diff --git a/library/Icinga/Test/BaseTestCase.php b/library/Icinga/Test/BaseTestCase.php index d88245ccd..0bf13212e 100644 --- a/library/Icinga/Test/BaseTestCase.php +++ b/library/Icinga/Test/BaseTestCase.php @@ -25,6 +25,7 @@ namespace Icinga\Test { use RuntimeException; use Mockery; use Zend_Config; + use Zend_Controller_Request_Abstract; use Zend_Test_PHPUnit_ControllerTestCase; use Icinga\Application\Icinga; use Icinga\Util\DateTimeFactory; @@ -142,23 +143,25 @@ namespace Icinga\Test { public function setUp() { parent::setUp(); - $this->setupIcingaMock(); + + $requestMock = Mockery::mock('Icinga\Web\Request'); + $requestMock->shouldReceive('getPathInfo')->andReturn('') + ->shouldReceive('getBaseUrl')->andReturn('/') + ->shouldReceive('getQuery')->andReturn(array()); + $this->setupIcingaMock($requestMock); } /** * Setup mock object for the application's bootstrap + * + * @param Zend_Controller_Request_Abstract $request The request to be returned by + * Icinga::app()->getFrontController()->getRequest() */ - protected function setupIcingaMock() + protected function setupIcingaMock(Zend_Controller_Request_Abstract $request) { $bootstrapMock = Mockery::mock('Icinga\Application\ApplicationBootstrap')->shouldDeferMissing(); $bootstrapMock->shouldReceive('getFrontController->getRequest')->andReturnUsing( - function () { - return Mockery::mock('Request') - ->shouldReceive('getPathInfo')->andReturn('') - ->shouldReceive('getBaseUrl')->andReturn('/') - ->shouldReceive('getQuery')->andReturn(array()) - ->getMock(); - } + function () use ($request) { return $request; } )->shouldReceive('getApplicationDir')->andReturn(self::$appDir); Icinga::setApp($bootstrapMock, true); diff --git a/library/Icinga/Web/Url.php b/library/Icinga/Web/Url.php index 2a9e21f3a..8bfc86aa4 100644 --- a/library/Icinga/Web/Url.php +++ b/library/Icinga/Web/Url.php @@ -30,16 +30,16 @@ namespace Icinga\Web; use Icinga\Application\Icinga; +use Icinga\Exception\ProgrammingError; /** - * Url class that provides convenient access to parameters, allows to modify query parameters and - * returns Urls reflecting all changes made to the url and to the parameters. + * Url class that provides convenient access to parameters, allows to modify query parameters and + * returns Urls reflecting all changes made to the url and to the parameters. * - * Direct instantiation is prohibited and should be done either with @see Url::fromRequest() or - * @see Url::fromUrlString() - * - * Currently, protocol, host and port are ignored and will be implemented when required + * Direct instantiation is prohibited and should be done either with @see Url::fromRequest() or + * @see Url::fromUrlString() * + * Currently, protocol, host and port are ignored and will be implemented when required */ class Url { @@ -48,28 +48,28 @@ class Url * * @var array */ - private $params = array(); + protected $params = array(); /** * An array to map aliases to valid parameters * * @var array */ - private $aliases = array(); + protected $aliases = array(); /** * The site anchor after the '#' * * @var string */ - private $anchor = ''; + protected $anchor = ''; /** * The relative path of this Url, without query parameters * * @var string */ - private $path = ''; + protected $path = ''; /** * The baseUrl that will be appended to @see Url::$path in order to @@ -77,10 +77,11 @@ class Url * * @var string */ - private $baseUrl = '/'; + protected $baseUrl = '/'; - private function __construct() + protected function __construct() { + } /** @@ -89,11 +90,10 @@ class Url * If $params are given, those will be added to the request's parameters * and overwrite any existing parameters * - * @param string $url The string representation of the Url to parse - * @param array $params Parameters that should additionally be considered for the Url - * @param Zend_Request $request A request to use instead of the default one + * @param array $params Parameters that should additionally be considered for the url + * @param Zend_Request $request A request to use instead of the default one * - * @return Url + * @return Url */ public static function fromRequest(array $params = array(), $request = null) { @@ -111,9 +111,9 @@ class Url /** * Return a request object that should be used for determining the URL * - * @return Zend_Abstract_Request + * @return Zend_Abstract_Request */ - private static function getRequest() + protected static function getRequest() { return Icinga::app()->getFrontController()->getRequest(); } @@ -124,38 +124,45 @@ class Url * If $params are given, those will be added to the urls parameters * and overwrite any existing parameters * - * @param string $url The string representation of the Url to parse - * @param array $params An array of parameters that should additionally be considered for the Url - * @param Zend_Request $request A request to use instead of the default one + * @param string $url The string representation of the url to parse + * @param array $params An array of parameters that should additionally be considered for the url + * @param Zend_Request $request A request to use instead of the default one * - * @return Url + * @return Url */ public static function fromPath($url, array $params = array(), $request = null) { - $urlObject = new Url(); if ($request === null) { $request = self::getRequest(); } + + if (!is_string($url)) { + throw new ProgrammingError(sprintf('url "%s" is not a string', $url)); + } + + $urlObject = new Url(); $urlObject->setBaseUrl($request->getBaseUrl()); - /* - * Fetch fragment manually and remove it from the url, to 'help' the parse_url() function - * parsing the url properly. Otherwise calling the function with a fragment, but without a - * query will cause unpredictable behaviour. - */ - $fragment = self::getUrlFragment($url); + // Fetch fragment manually and remove it from the url, to 'help' the parse_url() function + // parsing the url properly. Otherwise calling the function with a fragment, but without a + // query will cause unpredictable behaviour. $url = self::stripUrlFragment($url); $urlParts = parse_url($url); - if (isset($urlParts["path"])) { - $urlObject->setPath($urlParts["path"]); + if (strpos($urlParts["path"], $request->getBaseUrl()) === 0) { + $urlObject->setPath(substr($urlParts["path"], strlen($request->getBaseUrl()))); + } else { + $urlObject->setPath($urlParts["path"]); + } } if (isset($urlParts["query"])) { $urlParams = array(); parse_str($urlParts["query"], $urlParams); $params = array_merge($urlParams, $params); } + + $fragment = self::getUrlFragment($url); if ($fragment !== '') { $urlObject->setAnchor($fragment); } @@ -167,11 +174,11 @@ class Url /** * Get the fragment of a given url * - * @param $url The url containing the fragment. + * @param string $url The url containing the fragment. * - * @return string The fragment without the '#' + * @return string The fragment without the '#' */ - private static function getUrlFragment($url) + protected static function getUrlFragment($url) { $url = parse_url($url); if (isset($url['fragment'])) { @@ -184,11 +191,11 @@ class Url /** * Remove the fragment-part of a given url * - * @param $url string The url to strip from its fragment + * @param string $url The url to strip from its fragment * - * @return string The url without the fragment. + * @return string The url without the fragment */ - private static function stripUrlFragment($url) + protected static function stripUrlFragment($url) { return preg_replace('/#.*$/', '', $url); } @@ -209,9 +216,9 @@ class Url /** * Return the parameter for the given alias * - * @param string $alias The alias to translate + * @param string $alias The alias to translate * - * @return string The parameter name + * @return string The parameter name */ public function translateAlias($alias) { @@ -219,26 +226,28 @@ class Url } /** - * Overwrite the baseUrl. + * Overwrite the baseUrl * * If an empty Url is given '/' is used as the base * - * @param string $baseUrl The url path to use as the Url Base - * @return $this + * @param string $baseUrl The url path to use as the Url Base + * + * @return self */ public function setBaseUrl($baseUrl) { - if (trim($baseUrl) == '') { + if (($baseUrl = rtrim($baseUrl, '/ ')) === '') { $baseUrl = '/'; } + $this->baseUrl = $baseUrl; return $this; } /** - * Return the baseUrl set for this Url + * Return the baseUrl set for this url * - * @return string + * @return string */ public function getBaseUrl() { @@ -248,19 +257,22 @@ class Url /** * Set the relative path of this url, without query parameters * - * @param string $path The path to set + * @param string $path The path to set + * + * @return self */ public function setPath($path) { - $this->path = $path; + $this->path = ltrim($path, '/'); + return $this; } /** - * Return the relative path of this Url, without query parameters + * Return the relative path of this url, without query parameters * * If you want the relative path with query parameters use getRelativeUrl * - * @return string + * @return string */ public function getPath() { @@ -270,36 +282,38 @@ class Url /** * Return the relative url with query parameters as a string * - * @return string + * @return string */ public function getRelativeUrl() { if (empty($this->params)) { - return ltrim($this->path, '/') . $this->anchor; + return $this->path . $this->anchor; } + $params = array(); foreach ($this->params as $param => $value) { $params[$this->translateAlias($param)] = $value; } - return ltrim($this->path, '/') . '?' . http_build_query($params, '', '&') . $this->anchor; + + return $this->path . '?' . http_build_query($params, '', '&') . $this->anchor; } /** * Return the absolute url with query parameters as a string * - * @return string + * @return string */ public function getAbsoluteUrl() { - $url = $this->getRelativeUrl(); - return preg_replace('/\/{2,}/', '/', '/'.$this->baseUrl.'/'.$url); + return $this->baseUrl . ($this->baseUrl !== '/' ? '/' : '') . $this->getRelativeUrl(); } /** * Add a set of parameters to the query part if the keys don't exist yet * - * @param array $params The parameters to add - * @return self + * @param array $params The parameters to add + * + * @return self */ public function addParams(array $params) { @@ -310,8 +324,9 @@ class Url /** * Set and overwrite the given params if one if the same key already exists * - * @param array $params The parameters to set - * @return self + * @param array $params The parameters to set + * + * @return self */ public function overwriteParams(array $params) { @@ -322,8 +337,9 @@ class Url /** * Overwrite the parameters used in the query part * - * @param array $params The new parameters to use for the query part - * @return $this + * @param array $params The new parameters to use for the query part + * + * @return self */ public function setParams(array $params) { @@ -334,7 +350,7 @@ class Url /** * Return all parameters that will be used in the query part * - * @return array An associative key => value array containing all parameters + * @return array An associative key => value array containing all parameters */ public function getParams() { @@ -342,48 +358,52 @@ class Url } /** - * Return true if the Urls' query parameter with $key exists, otherwise false + * Return true if a urls' query parameter exists, otherwise false * - * @param $key A key to check for existing - * @return bool + * @param string $param The url parameter name to check + * + * @return bool */ - public function hasParam($key) + public function hasParam($param) { - return array_key_exists($key, $this->params); + return array_key_exists($param, $this->params); } /** - * Return the Url's query parameter with the name $key if exists, otherwise $default + * Return a url's query parameter if it exists, otherwise $default * - * @param $key A query parameter name to return if existing - * @param mixed $default A value to return when the parameter doesn't exist - * @return mixed + * @param string $param A query parameter name to return if existing + * @param mixed $default A value to return when the parameter doesn't exist + * + * @return mixed */ - public function getParam($key, $default = null) + public function getParam($param, $default = null) { - if ($this->hasParam($key)) { - return $this->params[$key]; + if ($this->hasParam($param)) { + return $this->params[$param]; } + return $default; } /** - * Set a single parameter $key, overwriting existing ones with the same key + * Set a single parameter, overwriting any existing one with the same name * - * @param string $key A string representing the key of the parameter - * @param array|string $value An array or string to set as the parameter value - * @return $this + * @param string $param The query parameter name + * @param array|string $value An array or string to set as the parameter value + * + * @return self */ - public function setParam($key, $value) + public function setParam($param, $value) { - $this->params[$key] = $value; + $this->params[$param] = $value; return $this; } /** * Set the url anchor-part * - * @param $anchor The site's anchor string without the '#' + * @param string $anchor The site's anchor string without the '#' * * @return self */ @@ -396,9 +416,9 @@ class Url /** * Remove provided key (if string) or keys (if array of string) from the query parameter array * - * @param string|array $keyOrArrayOfKeys An array of strings or a string representing the key(s) + * @param string|array $keyOrArrayOfKeys An array of strings or a string representing the key(s) * of the parameters to be removed - * @return $this + * @return self */ public function remove($keyOrArrayOfKeys) { @@ -407,45 +427,51 @@ class Url } else { $this->removeKey($keyOrArrayOfKeys); } + return $this; } /** * Remove all parameters with the parameter names in the $keys array * - * @param array $keys An array of strings containing parameter names to remove - * @return $this + * @param array $keys An array of strings containing parameter names to remove + * + * @return self */ public function removeKeys(array $keys) { foreach ($keys as $key) { $this->removeKey($key); } + return $this; } /** * Remove a single parameter with the provided parameter name $key * - * @param string $key The key to remove from the Url - * @return $this + * @param string $key The key to remove from the url + * + * @return self */ public function removeKey($key) { if (isset($this->params[$key])) { unset($this->params[$key]); } + return $this; } /** * Return a copy of this url without the parameter given * - * The argument can either a single query parameter name or an array of parameter names to + * The argument can be either a single query parameter name or an array of parameter names to * remove from the query list * - * @param string|array $keyOrArrayOfKeys A single string or an array containing parameter names - * @return Url + * @param string|array $keyOrArrayOfKeys A single string or an array containing parameter names + * + * @return Url */ public function getUrlWithout($keyOrArrayOfKeys) { @@ -456,7 +482,8 @@ class Url /** * Alias for @see Url::getAbsoluteUrl() - * @return mixed + * + * @return string */ public function __toString() { diff --git a/test/php/library/Icinga/Web/UrlTest.php b/test/php/library/Icinga/Web/UrlTest.php index 091737981..21a893b62 100644 --- a/test/php/library/Icinga/Web/UrlTest.php +++ b/test/php/library/Icinga/Web/UrlTest.php @@ -4,324 +4,340 @@ namespace Tests\Icinga\Web; -use \Mockery; +use Mockery; use Icinga\Web\Url; use Icinga\Test\BaseTestCase; -/** - * Tests for the Icinga\Web\Url class that provides convenient access to Url manipulation method - */ class UrlTest extends BaseTestCase { - /** - * Tests whether a simple Url without query parameters and baseUrl is correctly parsed and returns correct Urls - */ - function testFromStringWithoutQuery() + public function testWhetherFromRequestWorksWithoutARequest() { - $url = Url::fromPath('http://myHost/my/test/url.html'); - $this->assertEquals( - '/my/test/url.html', - $url->getPath(), - 'Assert the parsed url path to be equal to the input path' - ); - $this->assertEquals( - $url->getPath(), - '/' . $url->getRelativeUrl(), - 'Assert the path of an url without query to be equal the relative path' - ); - } - - /** - * Tests whether a simple Url without query parameters and with baseUrl is correctly parsed and returns correct Urls - */ - function testFromUrlWithBasePath() - { - $url = Url::fromPath('my/test/url.html'); - $url->setBaseUrl('the/path/to'); - $this->assertEquals( - '/the/path/to/my/test/url.html', - $url->getAbsoluteUrl(), - 'Assert the url path to be the base path with the relative path' - ); - } - - /** - * Tests whether query parameters in Urls are correctly recognized and decoded - */ - function testFromUrlWithKeyValueQuery() - { - $url = Url::fromPath('/my/test/url.html?param1=%25arg1¶m2=arg2'); - $this->assertEquals( - '/my/test/url.html', - $url->getPath(), - 'Assert the parsed url path to be equal to the input path' - ); - $this->assertEquals( - array( - 'param1' => '%arg1', - 'param2' => 'arg2' - ), - $url->getParams(), - 'Assert single key=value Url parameters to be correctly parsed and recognized' - ); - } - - /** - * Tests whether unnamed query parameters in Urls are correctly recognized and decoded - */ - function testFromUrlWithArrayInQuery() - { - $url = Url::fromPath('/my/test/url.html?param[]=%25val1¶m[]=%40val2'); - $this->assertEquals( - array( - 'param' => array('%val1', '@val2') - ), - $url->getParams(), - 'Assert arrays in param[] = value syntax to be correctly recognized and parsed as arrays' - ); - } - - /** - * Tests whether named query parameters in Urls are correctly recognized and decoded - */ - function testFromUrlWithAssociativeArrayInQuery() - { - $url = Url::fromPath('/my/test/url.html?param[value]=%25val1¶m[value2]=%40val2'); - $this->assertEquals( - array( - 'param' => array( - 'value' => '%val1', - 'value2' => '@val2' - ) - ), - $url->getParams(), - 'Assert arrays in param[] = value syntax to be correctly recognized and parsed as arrays' - ); - } - - /** - * Tests whether simple query parameters can be correctly added on an existing query and ends up in correct Urls - */ - function testAddQueryParameterToUrlWithoutQuery() - { - $url = Url::fromPath( - '/my/test/url.html', - array( - 'param1' => 'val1', - 'param2' => 'val2' - ) - ); - $url->setBaseUrl('path/to'); - $this->assertEquals( - '/path/to/my/test/url.html?param1=val1&param2=val2', - $url->getAbsoluteUrl(), - 'Assert additional parameters to be correctly added to the Url' - ); - } - - /** - * Test whether parameters are correctly added to existing query parameters - * and existing ones are correctly overwritten if they have the same key - */ - function testOverwritePartialQuery() - { - $url = Url::fromPath( - '/my/test/url.html?param1=oldval1', - array( - 'param1' => 'val1', - 'param2' => 'val2' - ) - ); - $url->setBaseUrl('path/to'); - $this->assertEquals( - '/path/to/my/test/url.html?param1=val1&param2=val2', - $url->getAbsoluteUrl(), - 'Assert additional parameters to be correctly added to the Url and overwriting existing parameters' - ); - } - - /** - * Test whether array parameters are correctly added to an existing Url and end up in correct Urls - */ - function testSetQueryWithArrayParameter() - { - $url = Url::fromPath( - '/my/test/url.html', - array( - 'flatarray' => array('val1', 'val2'), - 'param' => array('value1'=>'val1', 'value2' => 'val2') - ) - ); - $url->setBaseUrl('path/to'); - $this->assertEquals( - '/path/to/my/test/url.html?flatarray'.urlencode('[0]').'=val1&'. - 'flatarray'.urlencode('[1]').'=val2&'. - 'param'.urlencode('[value1]').'=val1&'. - 'param'.urlencode('[value2]').'=val2', - $url->getAbsoluteUrl(), - 'Assert array parameters to be correctly encoded and added to the Url' - ); - } - - /** - * Test whether Urls from the request are correctly parsed when no query is given - */ - function testUrlFromRequestWithoutQuery() - { - $request = Mockery::mock('RequestWithoutQuery'); + $request = Mockery::mock('Icinga\Web\Request'); $request->shouldReceive('getPathInfo')->andReturn('my/test/url.html') - ->shouldReceive('getBaseUrl')->andReturn('path/to') + ->shouldReceive('getBaseUrl')->andReturn('/path/to') + ->shouldReceive('getQuery')->andReturn(array('param1' => 'value1', 'param2' => 'value2')); + $this->setupIcingaMock($request); + + $url = Url::fromRequest(); + $this->assertEquals( + '/path/to/my/test/url.html?param1=value1&param2=value2', + $url->getAbsoluteUrl(), + 'Url::fromRequest does not reassemble the correct url from the global request' + ); + } + + public function testWhetherFromRequestWorksWithARequest() + { + $request = Mockery::mock('Icinga\Web\Request'); + $request->shouldReceive('getPathInfo')->andReturn('my/test/url.html') + ->shouldReceive('getBaseUrl')->andReturn('/path/to') ->shouldReceive('getQuery')->andReturn(array()); $url = Url::fromRequest(array(), $request); $this->assertEquals( '/path/to/my/test/url.html', $url->getAbsoluteUrl(), - 'Asserting absolute path resembling the requests path appended by the baseUrl' + 'Url::fromRequest does not reassemble the correct url from a given request' + ); + } + + public function testWhetherFromRequestAcceptsAdditionalParameters() + { + $request = Mockery::mock('Icinga\Web\Request'); + $request->shouldReceive('getPathInfo')->andReturn('') + ->shouldReceive('getBaseUrl')->andReturn('/') + ->shouldReceive('getQuery')->andReturn(array('key1' => 'val1')); + + $url = Url::fromRequest(array('key1' => 'newval1', 'key2' => 'val2'), $request); + $this->assertEquals( + 'val2', + $url->getParam('key2', 'wrongval'), + 'Url::fromRequest does not accept additional parameters' + ); + $this->assertEquals( + 'newval1', + $url->getParam('key1', 'wrongval1'), + 'Url::fromRequest does not overwrite existing parameters with additional ones' ); } /** - * Test whether Urls from the request are correctly parsed when a query is given + * @expectedException Icinga\Exception\ProgrammingError */ - function testUrlFromRequestWithQuery() + public function testWhetherFromPathProperlyHandlesInvalidUrls() { - $request = Mockery::mock('RequestWithoutQuery'); - $request->shouldReceive('getPathInfo')->andReturn('my/test/url.html') - ->shouldReceive('getBaseUrl')->andReturn('path/to') - ->shouldReceive('getQuery')->andReturn(array( - 'param1' => 'value1', - 'param2' => array('key1' => 'value1', 'key2' => 'value2') - ) + Url::fromPath(null); + } + + public function testWhetherFromPathAcceptsAdditionalParameters() + { + $url = Url::fromPath('/my/test/url.html', array('key' => 'value')); + + $this->assertEquals( + 'value', + $url->getParam('key', 'wrongvalue'), + 'Url::fromPath does not accept additional parameters' + ); + } + + public function testWhetherFromPathProperlyParsesUrlsWithoutQuery() + { + $url = Url::fromPath('/my/test/url.html'); + + $this->assertEquals( + '/', + $url->getBaseUrl(), + 'Url::fromPath does not recognize the correct base url' + ); + $this->assertEquals( + 'my/test/url.html', + $url->getPath(), + 'Url::fromPath does not recognize the correct url path' + ); + } + + /** + * @depends testWhetherFromPathProperlyParsesUrlsWithoutQuery + */ + public function testWhetherFromPathProperlyRecognizesTheBaseUrl() + { + $url = Url::fromPath( + '/path/to/my/test/url.html', + array(), + Mockery::mock(array('getBaseUrl' => '/path/to')) ); - $url = Url::fromRequest(array(), $request); $this->assertEquals( - '/path/to/my/test/url.html?param1=value1&'. - 'param2'.urlencode('[key1]').'=value1&'. - 'param2'.urlencode('[key2]').'=value2', + '/path/to/my/test/url.html', $url->getAbsoluteUrl(), - 'Asserting absolute path resembling the requests path appended by the baseUrl' + 'Url::fromPath does not properly differentiate between the base url and its path' ); } /** - * Test the @see Url::getParam($name, $default) function + * @depends testWhetherFromPathProperlyRecognizesTheBaseUrl */ - function testGetParameterByName() + public function testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters() + { + $url = Url::fromPath('/my/test/url.html?param1=%25arg1¶m2=arg+2' + . '¶m3[]=1¶m3[]=2¶m3[]=3¶m4[key1]=val1¶m4[key2]=val2'); + + $this->assertEquals( + '%arg1', + $url->getParam('param1', 'wrongval'), + 'Url::fromPath does not properly decode escaped characters in query parameter values' + ); + $this->assertEquals( + 'arg 2', + $url->getParam('param2', 'wrongval'), + 'Url::fromPath does not properly decode aliases characters in query parameter values' + ); + $this->assertEquals( + array('1', '2', '3'), + $url->getParam('param3'), + 'Url::fromPath does not properly reassemble query parameter values as sequenced values' + ); + $this->assertEquals( + array('key1' => 'val1', 'key2' => 'val2'), + $url->getParam('param4'), + 'Url::fromPath does not properly reassemble query parameters as associative arrays' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherTranslateAliasTranslatesKnownAliases() + { + $url = Url::fromPath('/my/test/url.html'); + $url->setAliases(array('foo' => 'bar')); + + $this->assertEquals( + 'bar', + $url->translateAlias('foo'), + 'Url::translateAlias does not translate a known alias' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherTranslateAliasDoesNotTranslateUnknownAliases() + { + $url = Url::fromPath('/my/test/url.html'); + $url->setAliases(array('foo' => 'bar')); + + $this->assertEquals( + 'fo', + $url->translateAlias('fo'), + 'Url::translateAlias does translate an unknown alias' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherGetAbsoluteUrlReturnsTheAbsoluteUrl() { $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); + $this->assertEquals( - "val", - $url->getParam("param", "wrongval"), - "Asserting a parameter can be fetched via getParam()" - ); - $this->assertEquals( - "val2", - $url->getParam("param2", "wrongval2"), - "Asserting a parameter can be fetched via getParam()" - ); - $this->assertEquals( - "nonexisting", - $url->getParam("param3", "nonexisting"), - "Asserting a non existing parameter returning the default value when fetched via getParam()" + '/my/test/url.html?param=val&param2=val2', + $url->getAbsoluteUrl(), + 'Url::getAbsoluteUrl does not return the absolute url' ); } /** - * Test the Url::remove function with a single key passed + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters */ - function testRemoveSingleParameter() + public function testWhetherGetRelativeUrlReturnsTheRelativeUrl() { $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); - $url->remove("param"); + $this->assertEquals( - "val2", - $url->getParam("param2", "wrongval2"), - "Asserting other parameters (param2) not being affected by remove" - ); - $this->assertEquals( - "rightval", - $url->getParam("param", "rightval"), - "Asserting a parameter (param) can be removed via remove" + 'my/test/url.html?param=val&param2=val2', + $url->getRelativeUrl(), + 'Url::getRelativeUrl does not return the relative url' ); } /** - * Test the Url::remove function with an array of keys passed + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters */ - function testRemoveMultipleParameters() + public function testWhetherGetParamReturnsTheCorrectParameter() { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); - $url->remove(array("param", "param2")); + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); + $this->assertEquals( - "val3", - $url->getParam("param3", "wrongval"), - "Asserting other parameters (param3) not being affected by remove" + 'val', + $url->getParam('param', 'wrongval'), + 'Url::getParam does not return the correct value for an existing parameter' ); $this->assertEquals( - "rightval", - $url->getParam("param", "rightval"), - "Asserting a parameter (param) can be removed via remove in a batch" + 'val2', + $url->getParam('param2', 'wrongval2'), + 'Url::getParam does not return the correct value for an existing parameter' ); $this->assertEquals( - "rightval", - $url->getParam("param2", "rightval"), - "Asserting a parameter (param2) can be removed via remove in a batch" + 'nonexisting', + $url->getParam('param3', 'nonexisting'), + 'Url::getParam does not return the default value for a non existing parameter' ); } /** - * Test the Url::without call and whether it returns a copy instead of working on the called object + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters */ - function testWithoutCall() + public function testWhetherRemoveRemovesAGivenSingleParameter() { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); - $url2 = $url->getUrlWithout(array("param")); - $this->assertNotEquals( - $url, - $url2, - "Asserting without creating a copy of the url" - ); - $this->assertTrue( - $url->hasParam("param"), - "Asserting the original Url not being affected when calling 'without'" - ); - $this->assertFalse( - $url2->hasParam("param"), - "Asserting the returned Url being without the passed parameter when calling 'without'" - ); - } + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); + $url->remove('param'); - function testAddParamAfterCreation() - { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); - $url->addParams(array( - "param4" => "val4", - "param3" => "newval3" - )); $this->assertEquals( - "val4", - $url->getParam("param4", "wrongval"), - "Asserting that a parameter can be added with addParam" + 'val2', + $url->getParam('param2', 'wrongval2'), + 'Url::remove removes not only the given parameter' ); $this->assertEquals( - "val3", - $url->getParam("param3", "wrongval"), - "Asserting that addParam doesn't overwrite existing parameters" + 'rightval', + $url->getParam('param', 'rightval'), + 'Url::remove does not remove the given parameter' ); } /** - * Test whether toString is the same as getAbsoluteUrl + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters */ - function testToString() + public function testWhetherRemoveRemovesAGivenSetOfParameters() { $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $url->remove(array('param', 'param2')); + + $this->assertEquals( + 'val3', + $url->getParam('param3', 'wrongval'), + 'Url::remove removes not only the given parameters' + ); + $this->assertEquals( + 'rightval', + $url->getParam('param', 'rightval'), + 'Url::remove does not remove all given parameters' + ); + $this->assertEquals( + 'rightval', + $url->getParam('param2', 'rightval'), + 'Url::remove does not remove all given parameters' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherGetUrlWithoutReturnsACopyOfTheUrlWithoutAGivenSetOfParameters() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $url2 = $url->getUrlWithout(array('param', 'param2')); + + $this->assertNotSame($url, $url2, 'Url::getUrlWithout does not return a new copy of the url'); + $this->assertEquals( + array('param3' => 'val3'), + $url2->getParams(), + 'Url::getUrlWithout does not remove a given set of parameters from the url' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherAddParamsDoesNotOverwriteExistingParameters() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $url->addParams(array('param4' => 'val4', 'param3' => 'newval3')); + + $this->assertEquals( + 'val4', + $url->getParam('param4', 'wrongval'), + 'Url::addParams does not add new parameters' + ); + $this->assertEquals( + 'val3', + $url->getParam('param3', 'wrongval'), + 'Url::addParams overwrites existing parameters' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherOverwriteParamsOverwritesExistingParameters() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $url->overwriteParams(array('param4' => 'val4', 'param3' => 'newval3')); + + $this->assertEquals( + 'val4', + $url->getParam('param4', 'wrongval'), + 'Url::addParams does not add new parameters' + ); + $this->assertEquals( + 'newval3', + $url->getParam('param3', 'wrongval'), + 'Url::addParams does not overwrite existing parameters' + ); + } + + /** + * @depends testWhetherGetAbsoluteUrlReturnsTheAbsoluteUrl + */ + public function testWhetherToStringConversionReturnsTheAbsoluteUrl() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $this->assertEquals( $url->getAbsoluteUrl(), (string) $url, - "Asserting whether toString returns the absolute Url" + 'Converting a url to string does not return the absolute url' ); } }