mirror of
https://github.com/guzzle/guzzle.git
synced 2025-02-12 11:30:49 +01:00
Adding tests for Url namespace and starting to sort tests
This commit is contained in:
parent
2dc27a9158
commit
02b910d0f2
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="./tests/bootstrap.php"
|
||||
<phpunit bootstrap="./vendor/autoload.php"
|
||||
colors="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
|
@ -39,6 +39,9 @@ class Client implements ClientInterface
|
||||
/** @var Collection Parameter object holding configuration data */
|
||||
private $config;
|
||||
|
||||
/** @var UriTemplate */
|
||||
private static $uriTemplate;
|
||||
|
||||
/**
|
||||
* Clients accept an array of constructor parameters.
|
||||
*
|
||||
@ -226,9 +229,15 @@ class Client implements ClientInterface
|
||||
*/
|
||||
private function expandTemplate($template, array $variables)
|
||||
{
|
||||
return function_exists('uri_template')
|
||||
? uri_template($template, $variables)
|
||||
: UriTemplate::getInstance()->expand($template, $variables);
|
||||
if (function_exists('uri_template')) {
|
||||
return uri_template($template, $variables);
|
||||
}
|
||||
|
||||
if (!self::$uriTemplate) {
|
||||
self::$uriTemplate = new UriTemplate();
|
||||
}
|
||||
|
||||
return self::$uriTemplate->expand($template, $variables);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,18 +80,26 @@ class QueryString extends Collection
|
||||
}
|
||||
|
||||
$result = '';
|
||||
$query = $this->aggregator->aggregate($this->data);
|
||||
foreach ($query as $key => $values) {
|
||||
foreach ($this->aggregator->aggregate($this->data) as $key => $values) {
|
||||
foreach ($values as $value) {
|
||||
if ($result) {
|
||||
$result .= '&';
|
||||
}
|
||||
if ($this->encoding == self::RFC1738) {
|
||||
$result .= urlencode($key) . '=' . urlencode($value);
|
||||
$result .= urlencode($key);
|
||||
if ($value !== null) {
|
||||
$result .= '=' . urlencode($value);
|
||||
}
|
||||
} elseif ($this->encoding == self::RFC3986) {
|
||||
$result .= rawurlencode($key) . '=' . rawurldecode($value);
|
||||
$result .= rawurlencode($key);
|
||||
if ($value !== null) {
|
||||
$result .= '=' . rawurlencode($value);
|
||||
}
|
||||
} else {
|
||||
$result .= $key . '=' . $value;
|
||||
$result .= $key;
|
||||
if ($value !== null) {
|
||||
$result .= '=' . $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,10 +127,15 @@ class QueryString extends Collection
|
||||
* @param string|bool $type One of 'RFC1738', 'RFC3986', or false to disable encoding
|
||||
*
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setEncodingType($type)
|
||||
{
|
||||
$this->encoding = $type;
|
||||
if ($type === false || $type === self::RFC1738 || $type === self::RFC3986) {
|
||||
$this->encoding = $type;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Invalid URL encoding type');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -11,9 +11,6 @@ class UriTemplate
|
||||
{
|
||||
const DEFAULT_PATTERN = '/\{([^\}]+)\}/';
|
||||
|
||||
/** @var self */
|
||||
private static $instance;
|
||||
|
||||
/** @var string URI template */
|
||||
private $template;
|
||||
|
||||
@ -39,15 +36,6 @@ class UriTemplate
|
||||
'%3B', '%3D'
|
||||
);
|
||||
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function expand($template, array $variables)
|
||||
{
|
||||
if ($this->regex == self::DEFAULT_PATTERN && false === strpos($template, '{')) {
|
||||
|
@ -93,7 +93,7 @@ class Url
|
||||
}
|
||||
|
||||
// Add the query string if present
|
||||
if (isset($parts['query'])) {
|
||||
if (isset($parts['query']) && strlen($parts['query'])) {
|
||||
$url .= '?' . $parts['query'];
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ class Url
|
||||
'host' => $this->host,
|
||||
'port' => $this->port,
|
||||
'path' => $this->getPath(),
|
||||
'query' => (string) $this->query ?: null,
|
||||
'query' => (string) $this->query,
|
||||
'fragment' => $this->fragment,
|
||||
);
|
||||
}
|
||||
@ -294,7 +294,7 @@ class Url
|
||||
return $this;
|
||||
}
|
||||
|
||||
$results = array();
|
||||
$results = [];
|
||||
$segments = $this->getPathSegments();
|
||||
foreach ($segments as $segment) {
|
||||
if ($segment == '..') {
|
||||
|
@ -2,32 +2,13 @@
|
||||
|
||||
namespace Guzzle\Tests;
|
||||
|
||||
use Guzzle\Common\HasDispatcherInterface;
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Http\Message\Response;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Tests\Http\Message\HeaderComparison;
|
||||
use Guzzle\Plugin\Mock\MockPlugin;
|
||||
use Guzzle\Service\Client;
|
||||
use Guzzle\Service\Builder\ServiceBuilderInterface;
|
||||
use Guzzle\Service\Builder\ServiceBuilder;
|
||||
use Guzzle\Tests\Mock\MockObserver;
|
||||
use Guzzle\Tests\Http\Server;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Base testcase class for all Guzzle testcases.
|
||||
*/
|
||||
abstract class GuzzleTestCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected static $mockBasePath;
|
||||
public static $serviceBuilder;
|
||||
public static $server;
|
||||
|
||||
private $requests = array();
|
||||
public $mockObserver;
|
||||
|
||||
/**
|
||||
* Get the global server object used throughout the unit tests of Guzzle
|
||||
*
|
||||
@ -46,184 +27,4 @@ abstract class GuzzleTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
return self::$server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the service builder to use for tests
|
||||
*
|
||||
* @param ServiceBuilderInterface $builder Service builder
|
||||
*/
|
||||
public static function setServiceBuilder(ServiceBuilderInterface $builder)
|
||||
{
|
||||
self::$serviceBuilder = $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a service builder object that can be used throughout the service tests
|
||||
*
|
||||
* @return ServiceBuilder
|
||||
*/
|
||||
public static function getServiceBuilder()
|
||||
{
|
||||
if (!self::$serviceBuilder) {
|
||||
throw new RuntimeException('No service builder has been set via setServiceBuilder()');
|
||||
}
|
||||
|
||||
return self::$serviceBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an event dispatcher has a subscriber
|
||||
*
|
||||
* @param HasDispatcherInterface $dispatcher
|
||||
* @param EventSubscriberInterface $subscriber
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasSubscriber(HasDispatcherInterface $dispatcher, EventSubscriberInterface $subscriber)
|
||||
{
|
||||
$class = get_class($subscriber);
|
||||
$all = array_keys(call_user_func(array($class, 'getSubscribedEvents')));
|
||||
|
||||
foreach ($all as $i => $event) {
|
||||
foreach ($dispatcher->getEventDispatcher()->getListeners($event) as $e) {
|
||||
if ($e[0] === $subscriber) {
|
||||
unset($all[$i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count($all) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a wildcard observer for an event dispatcher
|
||||
*
|
||||
* @param HasDispatcherInterface $hasEvent
|
||||
*
|
||||
* @return MockObserver
|
||||
*/
|
||||
public function getWildcardObserver(HasDispatcherInterface $hasDispatcher)
|
||||
{
|
||||
$class = get_class($hasDispatcher);
|
||||
$o = new MockObserver();
|
||||
$events = call_user_func(array($class, 'getAllEvents'));
|
||||
foreach ($events as $event) {
|
||||
$hasDispatcher->getEventDispatcher()->addListener($event, array($o, 'update'));
|
||||
}
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mock response base path
|
||||
*
|
||||
* @param string $path Path to mock response folder
|
||||
*
|
||||
* @return GuzzleTestCase
|
||||
*/
|
||||
public static function setMockBasePath($path)
|
||||
{
|
||||
self::$mockBasePath = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a request as being mocked
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function addMockedRequest(RequestInterface $request)
|
||||
{
|
||||
$this->requests[] = $request;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the mocked requests
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMockedRequests()
|
||||
{
|
||||
return $this->requests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a mock response for a client by mock file name
|
||||
*
|
||||
* @param string $path Relative path to the mock response file
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getMockResponse($path)
|
||||
{
|
||||
return $path instanceof Response
|
||||
? $path
|
||||
: MockPlugin::getMockFile(self::$mockBasePath . DIRECTORY_SEPARATOR . $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mock response from a mock file on the next client request.
|
||||
*
|
||||
* This method assumes that mock response files are located under the
|
||||
* Command/Mock/ directory of the Service being tested
|
||||
* (e.g. Unfuddle/Command/Mock/). A mock response is added to the next
|
||||
* request sent by the client.
|
||||
*
|
||||
* @param Client $client Client object to modify
|
||||
* @param string $paths Path to files within the Mock folder of the service
|
||||
*
|
||||
* @return MockPlugin returns the created mock plugin
|
||||
*/
|
||||
public function setMockResponse(Client $client, $paths)
|
||||
{
|
||||
$this->requests = array();
|
||||
$that = $this;
|
||||
$mock = new MockPlugin(null, true);
|
||||
$client->getEventDispatcher()->removeSubscriber($mock);
|
||||
$mock->getEventDispatcher()->addListener('mock.request', function(Event $event) use ($that) {
|
||||
$that->addMockedRequest($event['request']);
|
||||
});
|
||||
|
||||
foreach ((array) $paths as $path) {
|
||||
$mock->addResponse($this->getMockResponse($path));
|
||||
}
|
||||
|
||||
$client->getEventDispatcher()->addSubscriber($mock);
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare HTTP headers and use special markup to filter values
|
||||
* A header prefixed with '!' means it must not exist
|
||||
* A header prefixed with '_' means it must be ignored
|
||||
* A header value of '*' means anything after the * will be ignored
|
||||
*
|
||||
* @param array $filteredHeaders Array of special headers
|
||||
* @param array $actualHeaders Array of headers to check against
|
||||
*
|
||||
* @return array|bool Returns an array of the differences or FALSE if none
|
||||
*/
|
||||
public function compareHeaders($filteredHeaders, $actualHeaders)
|
||||
{
|
||||
$comparison = new HeaderComparison();
|
||||
|
||||
return $comparison->compare($filteredHeaders, $actualHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case insensitive assertContains
|
||||
*
|
||||
* @param string $needle Search string
|
||||
* @param string $haystack Search this
|
||||
* @param string $message Optional failure message
|
||||
*/
|
||||
public function assertContainsIns($needle, $haystack, $message = null)
|
||||
{
|
||||
$this->assertContains(strtolower($needle), strtolower($haystack), $message);
|
||||
}
|
||||
}
|
||||
|
44
tests/Guzzle/Tests/Url/DuplicateAggregatorTest.php
Normal file
44
tests/Guzzle/Tests/Url/DuplicateAggregatorTest.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Tests\Url;
|
||||
|
||||
use Guzzle\Url\DuplicateAggregator;
|
||||
|
||||
/**
|
||||
* @covers \Guzzle\Url\DuplicateAggregator
|
||||
* @covers \Guzzle\Url\AbstractAggregator
|
||||
*/
|
||||
class DuplicateAggregatorTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
{
|
||||
private $encodeData = [
|
||||
't' => [
|
||||
'v1' => ['a', '1'],
|
||||
'v2' => 'b',
|
||||
'v3' => ['v4' => 'c', 'v5' => 'd']
|
||||
]
|
||||
];
|
||||
|
||||
public function testEncodes()
|
||||
{
|
||||
$agg = new DuplicateAggregator();
|
||||
$result = $agg->aggregate($this->encodeData);
|
||||
$this->assertEquals(array(
|
||||
't[v1]' => ['a', '1'],
|
||||
't[v2]' => ['b'],
|
||||
't[v3][v4]' => ['c'],
|
||||
't[v3][v5]' => ['d'],
|
||||
), $result);
|
||||
}
|
||||
|
||||
public function testEncodesNoNumericIndices()
|
||||
{
|
||||
$agg = new DuplicateAggregator(false);
|
||||
$result = $agg->aggregate($this->encodeData);
|
||||
$this->assertEquals(array(
|
||||
't[v1]' => ['a', '1'],
|
||||
't[v2]' => ['b'],
|
||||
't[v3][v4]' => ['c'],
|
||||
't[v3][v5]' => ['d'],
|
||||
), $result);
|
||||
}
|
||||
}
|
45
tests/Guzzle/Tests/Url/PhpAggregatorTest.php
Normal file
45
tests/Guzzle/Tests/Url/PhpAggregatorTest.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Tests\Url;
|
||||
|
||||
use Guzzle\Url\PhpAggregator;
|
||||
|
||||
/**
|
||||
* @covers \Guzzle\Url\PhpAggregator
|
||||
* @covers \Guzzle\Url\AbstractAggregator
|
||||
*/
|
||||
class PhpAggregatorTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
{
|
||||
private $encodeData = [
|
||||
't' => [
|
||||
'v1' => ['a', '1'],
|
||||
'v2' => 'b',
|
||||
'v3' => ['v4' => 'c', 'v5' => 'd']
|
||||
]
|
||||
];
|
||||
|
||||
public function testEncodes()
|
||||
{
|
||||
$agg = new PhpAggregator();
|
||||
$result = $agg->aggregate($this->encodeData);
|
||||
$this->assertEquals(array(
|
||||
't[v1][0]' => ['a'],
|
||||
't[v1][1]' => ['1'],
|
||||
't[v2]' => ['b'],
|
||||
't[v3][v4]' => ['c'],
|
||||
't[v3][v5]' => ['d'],
|
||||
), $result);
|
||||
}
|
||||
|
||||
public function testEncodesNoNumericIndices()
|
||||
{
|
||||
$agg = new PhpAggregator(false);
|
||||
$result = $agg->aggregate($this->encodeData);
|
||||
$this->assertEquals(array(
|
||||
't[v1][]' => ['a', '1'],
|
||||
't[v2]' => ['b'],
|
||||
't[v3][v4]' => ['c'],
|
||||
't[v3][v5]' => ['d'],
|
||||
), $result);
|
||||
}
|
||||
}
|
176
tests/Guzzle/Tests/Url/QueryStringTest.php
Normal file
176
tests/Guzzle/Tests/Url/QueryStringTest.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Tests\Url;
|
||||
|
||||
use Guzzle\Url\QueryString;
|
||||
use Guzzle\Url\DuplicateAggregator;
|
||||
|
||||
class QueryStringTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
{
|
||||
public function testCanCastToString()
|
||||
{
|
||||
$q = new QueryString(['foo' => 'baz', 'bar' => 'bam boozle']);
|
||||
$this->assertEquals('foo=baz&bar=bam%20boozle', (string) $q);
|
||||
}
|
||||
|
||||
public function testCanDisableUrlEncoding()
|
||||
{
|
||||
$q = new QueryString(['bar' => 'bam boozle']);
|
||||
$q->setEncodingType(false);
|
||||
$this->assertEquals('bar=bam boozle', (string) $q);
|
||||
}
|
||||
|
||||
public function testCanSpecifyRfc1783UrlEncodingType()
|
||||
{
|
||||
$q = new QueryString(['bar abc' => 'bam boozle']);
|
||||
$q->setEncodingType(QueryString::RFC1738);
|
||||
$this->assertEquals('bar+abc=bam+boozle', (string) $q);
|
||||
}
|
||||
|
||||
public function testCanSpecifyRfc3986UrlEncodingType()
|
||||
{
|
||||
$q = new QueryString(['bar abc' => 'bam boozle', 'ሴ' => 'hi']);
|
||||
$q->setEncodingType(QueryString::RFC3986);
|
||||
$this->assertEquals('bar%20abc=bam%20boozle&%E1%88%B4=hi', (string) $q);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testValidatesEncodingType()
|
||||
{
|
||||
(new QueryString(['bar' => 'bam boozle']))->setEncodingType('foo');
|
||||
}
|
||||
|
||||
public function testAggregatesMultipleValues()
|
||||
{
|
||||
$q = new QueryString(['foo' => ['bar', 'baz']]);
|
||||
$this->assertEquals('foo%5B0%5D=bar&foo%5B1%5D=baz', (string) $q);
|
||||
}
|
||||
|
||||
public function testCanSetAggregator()
|
||||
{
|
||||
$agg = $this->getMockBuilder('Guzzle\Url\QueryAggregatorInterface')
|
||||
->setMethods('aggregate')
|
||||
->getMockForAbstractClass();
|
||||
|
||||
$q = new QueryString(['foo' => ['bar', 'baz']]);
|
||||
$q->setAggregator($agg);
|
||||
|
||||
$agg->expects($this->once())
|
||||
->method('aggregate')
|
||||
->will($this->returnValue(['foo' => ['barANDbaz']]));
|
||||
|
||||
$this->assertEquals('foo=barANDbaz', (string) $q);
|
||||
}
|
||||
|
||||
public function testAllowsMultipleValuesPerKey()
|
||||
{
|
||||
$q = new QueryString();
|
||||
$q->add('facet', 'size');
|
||||
$q->add('facet', 'width');
|
||||
$q->add('facet.field', 'foo');
|
||||
// Use the duplicate aggregator
|
||||
$q->setAggregator(new DuplicateAggregator());
|
||||
$this->assertEquals('facet=size&facet=width&facet.field=foo', (string) $q);
|
||||
}
|
||||
|
||||
public function parseQueryProvider()
|
||||
{
|
||||
return array(
|
||||
// Ensure that multiple query string values are allowed per value
|
||||
array('q=a&q=b', array('q' => array('a', 'b'))),
|
||||
// Ensure that PHP array style query string values are parsed
|
||||
array('q[]=a&q[]=b', array('q' => array('a', 'b'))),
|
||||
// Ensure that a single PHP array style query string value is parsed into an array
|
||||
array('q[]=a', array('q' => array('a'))),
|
||||
// Ensure that decimals are allowed in query strings
|
||||
array('q.a=a&q.b=b', array(
|
||||
'q.a' => 'a',
|
||||
'q.b' => 'b'
|
||||
)),
|
||||
// Ensure that query string values are percent decoded
|
||||
array('q%20a=a%20b', array('q a' => 'a b')),
|
||||
// Ensure null values can be added
|
||||
array('q&a', array('q' => null, 'a' => null)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider parseQueryProvider
|
||||
*/
|
||||
public function testParsesQueryStrings($query, $data)
|
||||
{
|
||||
$query = QueryString::fromString($query);
|
||||
$this->assertEquals($data, $query->toArray());
|
||||
}
|
||||
|
||||
public function testProperlyDealsWithDuplicateQueryStringValues()
|
||||
{
|
||||
$query = QueryString::fromString('foo=a&foo=b&?µ=c');
|
||||
$this->assertEquals(array('a', 'b'), $query->get('foo'));
|
||||
$this->assertEquals('c', $query->get('?µ'));
|
||||
}
|
||||
|
||||
public function testAllowsNullQueryStringValues()
|
||||
{
|
||||
$query = QueryString::fromString('foo');
|
||||
$this->assertEquals('foo', (string) $query);
|
||||
$query->set('foo', null);
|
||||
$this->assertEquals('foo', (string) $query);
|
||||
}
|
||||
|
||||
public function testAllowsFalsyQueryStringValues()
|
||||
{
|
||||
$query = QueryString::fromString('0');
|
||||
$this->assertEquals('0', (string) $query);
|
||||
$query->set('0', '');
|
||||
$this->assertSame('0=', (string) $query);
|
||||
}
|
||||
|
||||
public function testConvertsPlusSymbolsToSpaces()
|
||||
{
|
||||
$query = QueryString::fromString('var=foo+bar');
|
||||
$this->assertEquals('foo bar', $query->get('var'));
|
||||
}
|
||||
|
||||
public function testFromStringDoesntMangleZeroes()
|
||||
{
|
||||
$query = QueryString::fromString('var=0');
|
||||
$this->assertSame('0', $query->get('var'));
|
||||
}
|
||||
|
||||
public function testAllowsZeroValues()
|
||||
{
|
||||
$query = new QueryString(array(
|
||||
'foo' => 0,
|
||||
'baz' => '0',
|
||||
'bar' => null,
|
||||
'boo' => false
|
||||
));
|
||||
$this->assertEquals('foo=0&baz=0&bar&boo=', (string) $query);
|
||||
}
|
||||
|
||||
public function testFromStringDoesntStripTrailingEquals()
|
||||
{
|
||||
$query = QueryString::fromString('data=mF0b3IiLCJUZWFtIERldiJdfX0=');
|
||||
$this->assertEquals('mF0b3IiLCJUZWFtIERldiJdfX0=', $query->get('data'));
|
||||
}
|
||||
|
||||
public function testGuessesIfDuplicateAggregatorShouldBeUsed()
|
||||
{
|
||||
$query = QueryString::fromString('test=a&test=b');
|
||||
$this->assertEquals('test=a&test=b', (string) $query);
|
||||
}
|
||||
|
||||
public function testGuessesIfDuplicateAggregatorShouldBeUsedAndChecksForPhpStyle()
|
||||
{
|
||||
$query = QueryString::fromString('test[]=a&test[]=b');
|
||||
$this->assertEquals('test%5B0%5D=a&test%5B1%5D=b', (string) $query);
|
||||
}
|
||||
|
||||
public function testCastingToAndCreatingFromStringWithEmptyValuesIsFast()
|
||||
{
|
||||
$this->assertEquals('', (string) QueryString::fromString(''));
|
||||
}
|
||||
}
|
203
tests/Guzzle/Tests/Url/UriTemplateTest.php
Normal file
203
tests/Guzzle/Tests/Url/UriTemplateTest.php
Normal file
@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Tests\Parsers\UriTemplate;
|
||||
|
||||
use Guzzle\Url\UriTemplate;
|
||||
use Guzzle\Tests\GuzzleTestCase;
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Url\UriTemplate
|
||||
*/
|
||||
class UriTemplateTest extends GuzzleTestCase
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function templateProvider()
|
||||
{
|
||||
$params = array(
|
||||
'var' => 'value',
|
||||
'hello' => 'Hello World!',
|
||||
'empty' => '',
|
||||
'path' => '/foo/bar',
|
||||
'x' => '1024',
|
||||
'y' => '768',
|
||||
'null' => null,
|
||||
'list' => array('red', 'green', 'blue'),
|
||||
'keys' => array(
|
||||
"semi" => ';',
|
||||
"dot" => '.',
|
||||
"comma" => ','
|
||||
),
|
||||
'empty_keys' => array(),
|
||||
);
|
||||
|
||||
return array_map(function($t) use ($params) {
|
||||
$t[] = $params;
|
||||
return $t;
|
||||
}, array(
|
||||
array('foo', 'foo'),
|
||||
array('{var}', 'value'),
|
||||
array('{hello}', 'Hello%20World%21'),
|
||||
array('{+var}', 'value'),
|
||||
array('{+hello}', 'Hello%20World!'),
|
||||
array('{+path}/here', '/foo/bar/here'),
|
||||
array('here?ref={+path}', 'here?ref=/foo/bar'),
|
||||
array('X{#var}', 'X#value'),
|
||||
array('X{#hello}', 'X#Hello%20World!'),
|
||||
array('map?{x,y}', 'map?1024,768'),
|
||||
array('{x,hello,y}', '1024,Hello%20World%21,768'),
|
||||
array('{+x,hello,y}', '1024,Hello%20World!,768'),
|
||||
array('{+path,x}/here', '/foo/bar,1024/here'),
|
||||
array('{#x,hello,y}', '#1024,Hello%20World!,768'),
|
||||
array('{#path,x}/here', '#/foo/bar,1024/here'),
|
||||
array('X{.var}', 'X.value'),
|
||||
array('X{.x,y}', 'X.1024.768'),
|
||||
array('{/var}', '/value'),
|
||||
array('{/var,x}/here', '/value/1024/here'),
|
||||
array('{;x,y}', ';x=1024;y=768'),
|
||||
array('{;x,y,empty}', ';x=1024;y=768;empty'),
|
||||
array('{?x,y}', '?x=1024&y=768'),
|
||||
array('{?x,y,empty}', '?x=1024&y=768&empty='),
|
||||
array('?fixed=yes{&x}', '?fixed=yes&x=1024'),
|
||||
array('{&x,y,empty}', '&x=1024&y=768&empty='),
|
||||
array('{var:3}', 'val'),
|
||||
array('{var:30}', 'value'),
|
||||
array('{list}', 'red,green,blue'),
|
||||
array('{list*}', 'red,green,blue'),
|
||||
array('{keys}', 'semi,%3B,dot,.,comma,%2C'),
|
||||
array('{keys*}', 'semi=%3B,dot=.,comma=%2C'),
|
||||
array('{+path:6}/here', '/foo/b/here'),
|
||||
array('{+list}', 'red,green,blue'),
|
||||
array('{+list*}', 'red,green,blue'),
|
||||
array('{+keys}', 'semi,;,dot,.,comma,,'),
|
||||
array('{+keys*}', 'semi=;,dot=.,comma=,'),
|
||||
array('{#path:6}/here', '#/foo/b/here'),
|
||||
array('{#list}', '#red,green,blue'),
|
||||
array('{#list*}', '#red,green,blue'),
|
||||
array('{#keys}', '#semi,;,dot,.,comma,,'),
|
||||
array('{#keys*}', '#semi=;,dot=.,comma=,'),
|
||||
array('X{.var:3}', 'X.val'),
|
||||
array('X{.list}', 'X.red,green,blue'),
|
||||
array('X{.list*}', 'X.red.green.blue'),
|
||||
array('X{.keys}', 'X.semi,%3B,dot,.,comma,%2C'),
|
||||
array('X{.keys*}', 'X.semi=%3B.dot=..comma=%2C'),
|
||||
array('{/var:1,var}', '/v/value'),
|
||||
array('{/list}', '/red,green,blue'),
|
||||
array('{/list*}', '/red/green/blue'),
|
||||
array('{/list*,path:4}', '/red/green/blue/%2Ffoo'),
|
||||
array('{/keys}', '/semi,%3B,dot,.,comma,%2C'),
|
||||
array('{/keys*}', '/semi=%3B/dot=./comma=%2C'),
|
||||
array('{;hello:5}', ';hello=Hello'),
|
||||
array('{;list}', ';list=red,green,blue'),
|
||||
array('{;list*}', ';list=red;list=green;list=blue'),
|
||||
array('{;keys}', ';keys=semi,%3B,dot,.,comma,%2C'),
|
||||
array('{;keys*}', ';semi=%3B;dot=.;comma=%2C'),
|
||||
array('{?var:3}', '?var=val'),
|
||||
array('{?list}', '?list=red,green,blue'),
|
||||
array('{?list*}', '?list=red&list=green&list=blue'),
|
||||
array('{?keys}', '?keys=semi,%3B,dot,.,comma,%2C'),
|
||||
array('{?keys*}', '?semi=%3B&dot=.&comma=%2C'),
|
||||
array('{&var:3}', '&var=val'),
|
||||
array('{&list}', '&list=red,green,blue'),
|
||||
array('{&list*}', '&list=red&list=green&list=blue'),
|
||||
array('{&keys}', '&keys=semi,%3B,dot,.,comma,%2C'),
|
||||
array('{&keys*}', '&semi=%3B&dot=.&comma=%2C'),
|
||||
array('{.null}', ''),
|
||||
array('{.null,var}', '.value'),
|
||||
array('X{.empty_keys*}', 'X'),
|
||||
array('X{.empty_keys}', 'X'),
|
||||
// Test that missing expansions are skipped
|
||||
array('test{&missing*}', 'test'),
|
||||
// Test that multiple expansions can be set
|
||||
array('http://{var}/{var:2}{?keys*}', 'http://value/va?semi=%3B&dot=.&comma=%2C'),
|
||||
// Test more complex query string stuff
|
||||
array('http://www.test.com{+path}{?var,keys*}', 'http://www.test.com/foo/bar?var=value&semi=%3B&dot=.&comma=%2C')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider templateProvider
|
||||
*/
|
||||
public function testExpandsUriTemplates($template, $expansion, $params)
|
||||
{
|
||||
$uri = new UriTemplate($template);
|
||||
$this->assertEquals($expansion, $uri->expand($template, $params));
|
||||
}
|
||||
|
||||
public function expressionProvider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'{+var*}', array(
|
||||
'operator' => '+',
|
||||
'values' => array(
|
||||
array('value' => 'var', 'modifier' => '*')
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
'{?keys,var,val}', array(
|
||||
'operator' => '?',
|
||||
'values' => array(
|
||||
array('value' => 'keys', 'modifier' => ''),
|
||||
array('value' => 'var', 'modifier' => ''),
|
||||
array('value' => 'val', 'modifier' => '')
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
'{+x,hello,y}', array(
|
||||
'operator' => '+',
|
||||
'values' => array(
|
||||
array('value' => 'x', 'modifier' => ''),
|
||||
array('value' => 'hello', 'modifier' => ''),
|
||||
array('value' => 'y', 'modifier' => '')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider expressionProvider
|
||||
*/
|
||||
public function testParsesExpressions($exp, $data)
|
||||
{
|
||||
$template = new UriTemplate($exp);
|
||||
|
||||
// Access the config object
|
||||
$class = new \ReflectionClass($template);
|
||||
$method = $class->getMethod('parseExpression');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$exp = substr($exp, 1, -1);
|
||||
$this->assertEquals($data, $method->invokeArgs($template, array($exp)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket https://github.com/guzzle/guzzle/issues/90
|
||||
*/
|
||||
public function testAllowsNestedArrayExpansion()
|
||||
{
|
||||
$template = new UriTemplate();
|
||||
|
||||
$result = $template->expand('http://example.com{+path}{/segments}{?query,data*,foo*}', array(
|
||||
'path' => '/foo/bar',
|
||||
'segments' => array('one', 'two'),
|
||||
'query' => 'test',
|
||||
'data' => array(
|
||||
'more' => array('fun', 'ice cream')
|
||||
),
|
||||
'foo' => array(
|
||||
'baz' => array(
|
||||
'bar' => 'fizz',
|
||||
'test' => 'buzz'
|
||||
),
|
||||
'bam' => 'boo'
|
||||
)
|
||||
));
|
||||
|
||||
$this->assertEquals('http://example.com/foo/bar/one,two?query=test&more%5B0%5D=fun&more%5B1%5D=ice%20cream&baz%5Bbar%5D=fizz&baz%5Btest%5D=buzz&bam=boo', $result);
|
||||
}
|
||||
}
|
244
tests/Guzzle/Tests/Url/UrlTest.php
Normal file
244
tests/Guzzle/Tests/Url/UrlTest.php
Normal file
@ -0,0 +1,244 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Tests\Http;
|
||||
|
||||
use Guzzle\Url\QueryString;
|
||||
use Guzzle\Url\Url;
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Url\Url
|
||||
*/
|
||||
class UrlTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
{
|
||||
public function testEmptyUrl()
|
||||
{
|
||||
$url = Url::fromString('');
|
||||
$this->assertEquals('', (string) $url);
|
||||
}
|
||||
|
||||
public function testPortIsDeterminedFromScheme()
|
||||
{
|
||||
$this->assertEquals(80, Url::fromString('http://www.test.com/')->getPort());
|
||||
$this->assertEquals(443, Url::fromString('https://www.test.com/')->getPort());
|
||||
$this->assertEquals(null, Url::fromString('ftp://www.test.com/')->getPort());
|
||||
$this->assertEquals(8192, Url::fromString('http://www.test.com:8192/')->getPort());
|
||||
}
|
||||
|
||||
public function testCloneCreatesNewInternalObjects()
|
||||
{
|
||||
$u1 = Url::fromString('http://www.test.com/');
|
||||
$u2 = clone $u1;
|
||||
$this->assertNotSame($u1->getQuery(), $u2->getQuery());
|
||||
}
|
||||
|
||||
public function testValidatesUrlPartsInFactory()
|
||||
{
|
||||
$url = Url::fromString('/index.php');
|
||||
$this->assertEquals('/index.php', (string) $url);
|
||||
$this->assertFalse($url->isAbsolute());
|
||||
|
||||
$url = 'http://michael:test@test.com:80/path/123?q=abc#test';
|
||||
$u = Url::fromString($url);
|
||||
$this->assertEquals('http://michael:test@test.com/path/123?q=abc#test', (string) $u);
|
||||
$this->assertTrue($u->isAbsolute());
|
||||
}
|
||||
|
||||
public function testAllowsFalsyUrlParts()
|
||||
{
|
||||
$url = Url::fromString('http://0:50/0?0#0');
|
||||
$this->assertSame('0', $url->getHost());
|
||||
$this->assertEquals(50, $url->getPort());
|
||||
$this->assertSame('/0', $url->getPath());
|
||||
$this->assertEquals('0', (string) $url->getQuery());
|
||||
$this->assertSame('0', $url->getFragment());
|
||||
$this->assertEquals('http://0:50/0?0#0', (string) $url);
|
||||
|
||||
$url = Url::fromString('');
|
||||
$this->assertSame('', (string) $url);
|
||||
|
||||
$url = Url::fromString('0');
|
||||
$this->assertSame('0', (string) $url);
|
||||
}
|
||||
|
||||
public function testBuildsRelativeUrlsWithFalsyParts()
|
||||
{
|
||||
$url = Url::buildUrl(array(
|
||||
'host' => '0',
|
||||
'path' => '0',
|
||||
));
|
||||
|
||||
$this->assertSame('//0/0', $url);
|
||||
|
||||
$url = Url::buildUrl(array(
|
||||
'path' => '0',
|
||||
));
|
||||
$this->assertSame('0', $url);
|
||||
}
|
||||
|
||||
public function testUrlStoresParts()
|
||||
{
|
||||
$url = Url::fromString('http://test:pass@www.test.com:8081/path/path2/?a=1&b=2#fragment');
|
||||
$this->assertEquals('http', $url->getScheme());
|
||||
$this->assertEquals('test', $url->getUsername());
|
||||
$this->assertEquals('pass', $url->getPassword());
|
||||
$this->assertEquals('www.test.com', $url->getHost());
|
||||
$this->assertEquals(8081, $url->getPort());
|
||||
$this->assertEquals('/path/path2/', $url->getPath());
|
||||
$this->assertEquals('fragment', $url->getFragment());
|
||||
$this->assertEquals('a=1&b=2', (string) $url->getQuery());
|
||||
|
||||
$this->assertEquals(array(
|
||||
'fragment' => 'fragment',
|
||||
'host' => 'www.test.com',
|
||||
'pass' => 'pass',
|
||||
'path' => '/path/path2/',
|
||||
'port' => 8081,
|
||||
'query' => 'a=1&b=2',
|
||||
'scheme' => 'http',
|
||||
'user' => 'test'
|
||||
), $url->getParts());
|
||||
}
|
||||
|
||||
public function testHandlesPathsCorrectly()
|
||||
{
|
||||
$url = Url::fromString('http://www.test.com');
|
||||
$this->assertEquals('', $url->getPath());
|
||||
$url->setPath('test');
|
||||
$this->assertEquals('test', $url->getPath());
|
||||
|
||||
$url->setPath('/test/123/abc');
|
||||
$this->assertEquals(array('test', '123', 'abc'), $url->getPathSegments());
|
||||
|
||||
$parts = parse_url('http://www.test.com/test');
|
||||
$parts['path'] = '';
|
||||
$this->assertEquals('http://www.test.com', Url::buildUrl($parts));
|
||||
$parts['path'] = 'test';
|
||||
$this->assertEquals('http://www.test.com/test', Url::buildUrl($parts));
|
||||
}
|
||||
|
||||
public function testAddsQueryStringIfPresent()
|
||||
{
|
||||
$this->assertEquals('?foo=bar', Url::buildUrl(array(
|
||||
'query' => 'foo=bar'
|
||||
)));
|
||||
}
|
||||
|
||||
public function testAddsToPath()
|
||||
{
|
||||
// Does nothing here
|
||||
$this->assertEquals('http://e.com/base?a=1', (string) Url::fromString('http://e.com/base?a=1')->addPath(false));
|
||||
$this->assertEquals('http://e.com/base?a=1', (string) Url::fromString('http://e.com/base?a=1')->addPath(''));
|
||||
$this->assertEquals('http://e.com/base?a=1', (string) Url::fromString('http://e.com/base?a=1')->addPath('/'));
|
||||
|
||||
$this->assertEquals('http://e.com/base/relative?a=1', (string) Url::fromString('http://e.com/base?a=1')->addPath('relative'));
|
||||
$this->assertEquals('http://e.com/base/relative?a=1', (string) Url::fromString('http://e.com/base?a=1')->addPath('/relative'));
|
||||
}
|
||||
|
||||
/**
|
||||
* URL combination data provider
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function urlCombineDataProvider()
|
||||
{
|
||||
return array(
|
||||
array('http://www.example.com/', 'http://www.example.com/', 'http://www.example.com/'),
|
||||
array('http://www.example.com/path', '/absolute', 'http://www.example.com/absolute'),
|
||||
array('http://www.example.com/path', '/absolute?q=2', 'http://www.example.com/absolute?q=2'),
|
||||
array('http://www.example.com/path', 'more', 'http://www.example.com/path/more'),
|
||||
array('http://www.example.com/path', 'more?q=1', 'http://www.example.com/path/more?q=1'),
|
||||
array('http://www.example.com/', '?q=1', 'http://www.example.com/?q=1'),
|
||||
array('http://www.example.com/path', 'http://test.com', 'http://test.com'),
|
||||
array('http://www.example.com:8080/path', 'http://test.com', 'http://test.com'),
|
||||
array('http://www.example.com:8080/path', '?q=2#abc', 'http://www.example.com:8080/path?q=2#abc'),
|
||||
array('http://u:a@www.example.com/path', 'test', 'http://u:a@www.example.com/path/test'),
|
||||
array('http://www.example.com/path', 'http://u:a@www.example.com/', 'http://u:a@www.example.com/'),
|
||||
array('/path?q=2', 'http://www.test.com/', 'http://www.test.com/path?q=2'),
|
||||
array('http://api.flickr.com/services/', 'http://www.flickr.com/services/oauth/access_token', 'http://www.flickr.com/services/oauth/access_token'),
|
||||
array('https://www.example.com/path', '//foo.com/abc', 'https://foo.com/abc'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider urlCombineDataProvider
|
||||
*/
|
||||
public function testCombinesUrls($a, $b, $c)
|
||||
{
|
||||
$this->assertEquals($c, (string) Url::fromString($a)->combine($b));
|
||||
}
|
||||
|
||||
public function testHasGettersAndSetters()
|
||||
{
|
||||
$url = Url::fromString('http://www.test.com/');
|
||||
$this->assertEquals('example.com', $url->setHost('example.com')->getHost());
|
||||
$this->assertEquals('8080', $url->setPort(8080)->getPort());
|
||||
$this->assertEquals('/foo/bar', $url->setPath(array('foo', 'bar'))->getPath());
|
||||
$this->assertEquals('a', $url->setPassword('a')->getPassword());
|
||||
$this->assertEquals('b', $url->setUsername('b')->getUsername());
|
||||
$this->assertEquals('abc', $url->setFragment('abc')->getFragment());
|
||||
$this->assertEquals('https', $url->setScheme('https')->getScheme());
|
||||
$this->assertEquals('a=123', (string) $url->setQuery('a=123')->getQuery());
|
||||
$this->assertEquals('https://b:a@example.com:8080/foo/bar?a=123#abc', (string) $url);
|
||||
$this->assertEquals('b=boo', (string) $url->setQuery(new QueryString(array(
|
||||
'b' => 'boo'
|
||||
)))->getQuery());
|
||||
$this->assertEquals('https://b:a@example.com:8080/foo/bar?b=boo#abc', (string) $url);
|
||||
}
|
||||
|
||||
public function testSetQueryAcceptsArray()
|
||||
{
|
||||
$url = Url::fromString('http://www.test.com');
|
||||
$url->setQuery(array('a' => 'b'));
|
||||
$this->assertEquals('http://www.test.com?a=b', (string) $url);
|
||||
}
|
||||
|
||||
public function urlProvider()
|
||||
{
|
||||
return array(
|
||||
array('/foo/..', '/'),
|
||||
array('//foo//..', '/'),
|
||||
array('/foo/../..', '/'),
|
||||
array('/foo/../.', '/'),
|
||||
array('/./foo/..', '/'),
|
||||
array('/./foo', '/foo'),
|
||||
array('/./foo/', '/foo/'),
|
||||
array('/./foo/bar/baz/pho/../..', '/foo/bar'),
|
||||
array('*', '*'),
|
||||
array('/foo', '/foo'),
|
||||
array('/abc/123/../foo/', '/abc/foo/')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider urlProvider
|
||||
*/
|
||||
public function testNormalizesPaths($path, $result)
|
||||
{
|
||||
$url = Url::fromString('http://www.example.com');
|
||||
$url->setPath($path)->normalizePath();
|
||||
$this->assertEquals($result, $url->getPath());
|
||||
}
|
||||
|
||||
public function testSettingHostWithPortModifiesPort()
|
||||
{
|
||||
$url = Url::fromString('http://www.example.com');
|
||||
$url->setHost('foo:8983');
|
||||
$this->assertEquals('foo', $url->getHost());
|
||||
$this->assertEquals(8983, $url->getPort());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testValidatesUrlCanBeParsed()
|
||||
{
|
||||
Url::fromString('foo:////');
|
||||
}
|
||||
|
||||
public function testConvertsSpecialCharsInPathWhenCastingToString()
|
||||
{
|
||||
$url = Url::fromString('http://foo.com/baz bar?a=b');
|
||||
$url->addPath('?');
|
||||
$this->assertEquals('http://foo.com/baz%20bar/%3F?a=b', (string) $url);
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
// Ensure that composer has installed all dependencies
|
||||
if (!file_exists(dirname(__DIR__) . '/composer.lock')) {
|
||||
die("Dependencies must be installed using composer:\n\nphp composer.phar install --dev\n\n"
|
||||
. "See http://getcomposer.org for help with installing composer\n");
|
||||
}
|
||||
|
||||
require_once 'PHPUnit/TextUI/TestRunner.php';
|
||||
|
||||
// Include the phar files if testing against the phars
|
||||
if (get_cfg_var('guzzle_phar')) {
|
||||
require get_cfg_var('guzzle_phar');
|
||||
}
|
||||
|
||||
// Include the composer autoloader
|
||||
$autoloader = require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
// Add the services file to the default service builder
|
||||
$servicesFile = __DIR__ . '/Guzzle/Tests/TestData/services/services.json';
|
||||
Guzzle\Tests\GuzzleTestCase::setServiceBuilder(Guzzle\Service\Builder\ServiceBuilder::factory($servicesFile));
|
Loading…
x
Reference in New Issue
Block a user