[BrowserKit] added the component

This commit is contained in:
Fabien Potencier 2010-04-19 14:12:42 +02:00
parent e09f730243
commit 79b39157e2
12 changed files with 1659 additions and 0 deletions

View File

@ -0,0 +1,376 @@
<?php
namespace Symfony\Components\BrowserKit;
use Symfony\Components\DomCrawler\Crawler;
use Symfony\Components\DomCrawler\Link;
use Symfony\Components\DomCrawler\Form;
use Symfony\Components\Process\PhpProcess;
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Client simulates a browser.
*
* To make the actual request, you need to implement the doRequest() method.
*
* If you want to be able to run requests in their own process (insulated flag),
* you need to also implement the getScript() method.
*
* @package Symfony
* @subpackage Components_BrowserKit
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
abstract class Client
{
protected $history;
protected $cookieJar;
protected $server;
protected $request;
protected $response;
protected $crawler;
protected $insulated;
protected $redirect;
/**
* Constructor.
*
* @param array $server The server parameters (equivalent of $_SERVER)
* @param Symfony\Components\BrowserKit\History $history A History instance to store the browser history
* @param Symfony\Components\BrowserKit\CookieJar $cookieJar A CookieJar instance to store the cookies
*/
public function __construct(array $server = array(), History $history = null, CookieJar $cookieJar = null)
{
$this->setServerParameters($server);
$this->history = null === $history ? new History() : $history;
$this->cookieJar = null === $cookieJar ? new CookieJar() : $cookieJar;
$this->insulated = false;
}
/**
* Sets the insulated flag.
*
* @param Boolean $insulated Whether to insulate the requests or not
*/
public function insulate($insulated = true)
{
if (!class_exists('Symfony\\Components\\Process\\Process'))
{
// @codeCoverageIgnoreStart
throw new \RuntimeException('Unable to isolate requests as the Symfony Process Component is not installed.');
// @codeCoverageIgnoreEnd
}
$this->insulated = (Boolean) $insulated;
}
/**
* Sets server parameters.
*
* @param array $server An array of server parameters
*/
public function setServerParameters(array $server)
{
$this->server = array_merge(array(
'HTTP_HOST' => 'localhost',
'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3',
), $server);
}
/**
* Returns the History instance.
*
* @return Symfony\Components\BrowserKit\History A History instance
*/
public function getHistory()
{
return $this->history;
}
/**
* Returns the CookieJar instance.
*
* @return Symfony\Components\BrowserKit\CookieJar A CookieJar instance
*/
public function getCookieJar()
{
return $this->cookieJar;
}
/**
* Returns the current Crawler instance.
*
* @return Symfony\Components\DomCrawler\Crawler A Crawler instance
*/
public function getCrawler()
{
return $this->crawler;
}
/**
* Returns the current Response instance.
*
* @return Symfony\Components\BrowserKit\Response A Response instance
*/
public function getResponse()
{
return $this->response;
}
/**
* Returns the current Request instance.
*
* @return Symfony\Components\BrowserKit\Request A Request instance
*/
public function getRequest()
{
return $this->request;
}
/**
* Clicks on a given link.
*
* @param Symfony\Components\BrowserKit\Link $link A Link instance
*/
public function click(Link $link)
{
return $this->request($link->getMethod(), $link->getUri());
}
/**
* Submits a form.
*
* @param Symfony\Components\BrowserKit\Form $form A Form instance
* @param array $values An array of form field values
*/
public function submit(Form $form, array $values = array())
{
$form->setValues($values);
return $this->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), array(), $form->getPhpFiles());
}
/**
* Calls a URI.
*
* @param string $method The request method
* @param string $uri The URI to fetch
* @param array $parameters The Request parameters
* @param array $headers The headers
* @param array $files The files
* @param array $server The server parameters
* @param Boolean $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload())
*
* @return Symfony\Components\DomCrawler\Crawler
*/
public function request($method, $uri, $parameters = array(), $headers = array(), $files = array(), $server = array(), $changeHistory = true)
{
$uri = $this->getAboluteUri($uri);
$server = array_merge($this->server, $server);
if (!$this->history->isEmpty())
{
$server['HTTP_REFERER'] = $this->history->current()->getUri();
}
$server['HTTP_HOST'] = parse_url($uri, PHP_URL_HOST);
$server['HTTPS'] = 'https' == parse_url($uri, PHP_URL_SCHEME);
$request = new Request($uri, $method, $parameters, $files, $this->cookieJar->getValues($uri), $server);
$this->request = $this->filterRequest($request);
if (true === $changeHistory)
{
$this->history->add($request);
}
if ($this->insulated)
{
$this->response = $this->doRequestInProcess($this->request);
}
else
{
$this->response = $this->doRequest($this->request);
}
$response = $this->filterResponse($this->response);
$this->cookieJar->updateFromResponse($response);
$this->redirect = $response->getHeader('Location');
return $this->crawler = $this->createCrawlerFromContent($request->getUri(), $response->getContent(), $response->getHeader('Content-Type'));
}
/**
* Makes a request in another process.
*
* @param Request $request A Request instance
*
* @param Response $response A Response instance
*/
protected function doRequestInProcess($request)
{
$process = new PhpProcess($this->getScript($request));
$process->run();
if ($process->getExitCode() > 0)
{
throw new \RuntimeException($process->getErrorOutput());
}
return unserialize($process->getOutput());
}
/**
* Makes a request.
*
* @param Request $request A Request instance
*
* @param Response $response A Response instance
*/
abstract protected function doRequest($request);
/**
* Returns the script to execute when the request must be insulated.
*
* @param Request $request A Request instance
*/
protected function getScript($request)
{
// @codeCoverageIgnoreStart
throw new \LogicException('To insulate requests, you need to override the getScript() method.');
// @codeCoverageIgnoreEnd
}
protected function filterRequest(Request $request)
{
return $request;
}
protected function filterResponse($response)
{
return $response;
}
protected function createCrawlerFromContent($uri, $content, $type)
{
$crawler = new Crawler(null, $uri);
$crawler->addContent($content, $type);
return $crawler;
}
/**
* Goes back in the browser history.
*/
public function back()
{
return $this->requestFromRequest($this->history->back(), false);
}
/**
* Goes forward in the browser history.
*/
public function forward()
{
return $this->requestFromRequest($this->history->forward(), false);
}
/**
* Reloads the current browser.
*/
public function reload()
{
return $this->requestFromRequest($this->history->current(), false);
}
/**
* Follow redirects?
*
* @throws sfException If request was not a redirect
*
* @return Symfony\Components\BrowserKit\Client
*/
public function followRedirect()
{
if (null === $this->redirect)
{
throw new \LogicException('The request was not redirected.');
}
return $this->request('get', $this->redirect);
}
/**
* Restarts the client.
*
* It flushes all cookies.
*/
public function restart()
{
$this->cookieJar->clear();
$this->history->clear();
}
protected function getAboluteUri($uri)
{
// already absolute?
if ('http' === substr($uri, 0, 4))
{
return $uri;
}
if (!$this->history->isEmpty())
{
$currentUri = $this->history->current()->getUri();
}
else
{
$currentUri = sprintf('http%s://%s/',
isset($this->server['HTTPS']) ? 's' : '',
isset($this->server['HTTP_HOST']) ? $this->server['HTTP_HOST'] : 'localhost'
);
}
// anchor?
if (!$uri || '#' == $uri[0])
{
return preg_replace('/#.*?$/', '', $currentUri).$uri;
}
if ('/' !== $uri[0])
{
$path = parse_url($currentUri, PHP_URL_PATH);
if ('/' !== substr($path, -1))
{
$path = substr($path, 0, strrpos($path, '/') + 1);
}
$uri = $path.$uri;
}
return preg_replace('#^(.*?//[^/]+)\/.*$#', '$1', $currentUri).$uri;
}
/**
* Makes a request from a Request object directly.
*
* @param Symfony\Components\BrowserKit\Request $request A Request instance
* @param Boolean $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload())
*
* @return Symfony\Components\DomCrawler\Crawler
*/
protected function requestFromRequest(Request $request, $changeHistory = true)
{
return $this->request($request->getMethod(), $request->getUri(), $request->getParameters(), $request->getFiles(), array(), $request->getServer(), $changeHistory);
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace Symfony\Components\BrowserKit;
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Cookie represents an HTTP cookie.
*
* @package Symfony
* @subpackage Components_BrowserKit
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Cookie
{
protected $name;
protected $value;
protected $expire;
protected $path;
protected $domain;
protected $secure;
/**
* Sets a cookie.
*
* @param string $name The cookie name
* @param string $value The value of the cookie
* @param string $expire The time the cookie expires
* @param string $path The path on the server in which the cookie will be available on
* @param string $domain The domain that the cookie is available
* @param bool $secure Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client
*/
public function __construct($name, $value, $expire = 0, $path = '/', $domain = '', $secure = false)
{
$this->name = $name;
$this->value = $value;
$this->expire = (integer) $expire;
$this->path = empty($path) ? '/' : $path;
$this->domain = $domain;
$this->secure = (Boolean) $secure;
}
/**
* Gets the name of the cookie.
*
* @return string The cookie name
*/
public function getName()
{
return $this->name;
}
/**
* Gets the value of the cookie.
*
* @return string The cookie value
*/
public function getValue()
{
return $this->value;
}
/**
* Gets the expire time of the cookie.
*
* @return string The cookie expire time
*/
public function getExpireTime()
{
return $this->expire;
}
/**
* Gets the path of the cookie.
*
* @return string The cookie path
*/
public function getPath()
{
return $this->path;
}
/**
* Gets the domain of the cookie.
*
* @return string The cookie domain
*/
public function getDomain()
{
return $this->domain;
}
/**
* Returns the secure flag of the cookie.
*
* @return Boolean The cookie secure flag
*/
public function isSecure()
{
return $this->secure;
}
/**
* Returns true if the cookie has expired.
*
* @return Boolean true if the cookie has expired, false otherwise
*/
public function isExpired()
{
return $this->expire && $this->expire < time();
}
}

View File

@ -0,0 +1,151 @@
<?php
namespace Symfony\Components\BrowserKit;
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* CookieJar.
*
* @package Symfony
* @subpackage Components_BrowserKit
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class CookieJar
{
protected $cookieJar = array();
/**
* Sets a cookie.
*
* @param Symfony\Components\BrowserKit\Cookie $cookie A Cookie instance
*/
public function set(Cookie $cookie)
{
$this->cookieJar[$cookie->getName()] = $cookie;
}
/**
* Gets a cookie by name.
*
* @param string $name The cookie name
*
* @return Symfony\Components\BrowserKit\Cookie|null A Cookie instance or null if the cookie does not exist
*/
public function get($name)
{
$this->flushExpiredCookies();
return isset($this->cookieJar[$name]) ? $this->cookieJar[$name] : null;
}
/**
* Removes a cookie by name.
*
* @param string $name The cookie name
*/
public function expire($name)
{
unset($this->cookieJar[$name]);
}
/**
* Removes all the cookies from the jar.
*/
public function clear()
{
$this->cookieJar = array();
}
/**
* Updates the cookie jar from a Response object.
*
* @param Symfony\Components\BrowserKit\Response $response A Response object
*/
public function updateFromResponse(Response $response)
{
$this->clear();
foreach ($response->getCookies() as $name => $cookie)
{
$this->set(new Cookie(
$name,
isset($cookie['value']) ? $cookie['value'] : '',
isset($cookie['expire']) ? $cookie['expire'] : 0,
isset($cookie['path']) ? $cookie['path'] : '/',
isset($cookie['domain']) ? $cookie['domain'] : '',
isset($cookie['secure']) ? $cookie['secure'] : false
));
}
}
/**
* Returns not yet expired cookies.
*
* @return array An array of cookies
*/
public function all()
{
$this->flushExpiredCookies();
return $this->cookieJar;
}
/**
* Returns not yet expired cookie values for the given URI.
*
* @param string $uri A URI
*
* @return array An array of cookie values
*/
public function getValues($uri)
{
$this->flushExpiredCookies();
$parts = parse_url($uri);
$cookies = array();
foreach ($this->cookieJar as $cookie)
{
if ($cookie->getDomain() && $cookie->getDomain() != substr($parts['host'], -strlen($cookie->getDomain())))
{
continue;
}
if ($cookie->getPath() != substr($parts['path'], 0, strlen($cookie->getPath())))
{
continue;
}
if ($cookie->isSecure() && 'https' != $parts['scheme'])
{
continue;
}
$cookies[$cookie->getName()] = $cookie->getValue();
}
return $cookies;
}
/**
* Removes all expired cookies.
*/
public function flushExpiredCookies()
{
$cookies = $this->cookieJar;
foreach ($cookies as $name => $cookie)
{
if ($cookie->isExpired())
{
unset($this->cookieJar[$name]);
}
}
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace Symfony\Components\BrowserKit;
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* History.
*
* @package Symfony
* @subpackage Components_BrowserKit
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class History
{
protected $stack = array();
protected $position = -1;
/**
* Constructor.
*/
public function __construct()
{
$this->clear();
}
/**
* Clears the history.
*/
public function clear()
{
$this->stack = array();
$this->position = -1;
}
/**
* Adds a Request to the history.
*
* @param Symfony\Components\BrowserKit\Request $request A Request instance
*/
public function add(Request $request)
{
$this->stack = array_slice($this->stack, 0, $this->position + 1);
$this->stack[] = clone $request;
$this->position = count($this->stack) - 1;
}
/**
* Returns true if the history is empty.
*
* @return Boolean true if the history is empty, false otherwise
*/
public function isEmpty()
{
return count($this->stack) == 0;
}
/**
* Goes back in the history.
*
* @return Symfony\Components\BrowserKit\Request A Request instance
*
* @throws \LogicException if the stack is already on the first page
*/
public function back()
{
if ($this->position < 1)
{
throw new \LogicException('You are already on the first page.');
}
return clone $this->stack[--$this->position];
}
/**
* Goes forward in the history.
*
* @return Symfony\Components\BrowserKit\Request A Request instance
*
* @throws \LogicException if the stack is already on the last page
*/
public function forward()
{
if ($this->position > count($this->stack) - 2)
{
throw new \LogicException('You are already on the last page.');
}
return clone $this->stack[++$this->position];
}
/**
* Returns the current element in the history.
*
* @return Symfony\Components\BrowserKit\Request A Request instance
*
* @throws \LogicException if the stack is empty
*/
public function current()
{
if (-1 == $this->position)
{
throw new \LogicException('The page history is empty.');
}
return clone $this->stack[$this->position];
}
}

View File

@ -0,0 +1,108 @@
<?php
namespace Symfony\Components\BrowserKit;
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Request object.
*
* @package Symfony
* @subpackage Components_BrowserKit
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Request
{
protected $uri;
protected $method;
protected $parameters;
protected $files;
protected $cookies;
protected $server;
/**
* Constructor.
*
* @param string $uri The request URI
* @param array $parameters The request parameters
* @param array $files An array of uploaded files
* @param array $cookies An array of cookies
* @param array $server An array of server parameters
*/
public function __construct($uri, $method, array $parameters = array(), array $files = array(), array $cookies = array(), array $server = array())
{
$this->uri = $uri;
$this->method = $method;
$this->parameters = $parameters;
$this->files = $files;
$this->cookies = $cookies;
$this->server = $server;
}
/**
* Gets the request URI.
*
* @return string The request URI
*/
public function getUri()
{
return $this->uri;
}
/**
* Gets the request HTTP method.
*
* @return string The request HTTP method
*/
public function getMethod()
{
return $this->method;
}
/**
* Gets the request parameters.
*
* @return array The request parameters
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Gets the request server files.
*
* @return array The request files
*/
public function getFiles()
{
return $this->files;
}
/**
* Gets the request cookies.
*
* @return array The request cookies
*/
public function getCookies()
{
return $this->cookies;
}
/**
* Gets the request server parameters.
*
* @return array The request server parameters
*/
public function getServer()
{
return $this->server;
}
}

View File

@ -0,0 +1,103 @@
<?php
namespace Symfony\Components\BrowserKit;
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Response object.
*
* @package Symfony
* @subpackage Components_BrowserKit
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Response
{
protected $content;
protected $status;
protected $headers;
protected $cookies;
/**
* Constructor.
*
* @param string $content The content of the response
* @param integer $status The response status code
* @param array $headers An array of headers
* @param array $cookies An array of cookies
*/
public function __construct($content = '', $status = 200, $headers = array(), $cookies = array())
{
$this->content = $content;
$this->status = $status;
$this->headers = $headers;
$this->cookies = $cookies;
}
/**
* Gets the response content.
*
* @return string The response content
*/
public function getContent()
{
return $this->content;
}
/**
* Gets the response status code.
*
* @return integer The response status code
*/
public function getStatus()
{
return $this->status;
}
/**
* Gets the response headers.
*
* @return array The response headers
*/
public function getHeaders()
{
return $this->headers;
}
/**
* Gets a response header.
*
* @param string $header The header name
*
* @return string The header value
*/
public function getHeader($header)
{
foreach ($this->headers as $key => $value)
{
if (str_replace('-', '_', strtolower($key)) == str_replace('-', '_', strtolower($header)))
{
return $value;
}
}
return null;
}
/**
* Gets the response cookies.
*
* @return array The response cookies
*/
public function getCookies()
{
return $this->cookies;
}
}

View File

@ -0,0 +1,303 @@
<?php
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Components\BrowserKit;
use Symfony\Components\BrowserKit\Client;
use Symfony\Components\BrowserKit\History;
use Symfony\Components\BrowserKit\CookieJar;
use Symfony\Components\BrowserKit\Request;
use Symfony\Components\BrowserKit\Response;
class TestClient extends Client
{
protected $nextResponse = null;
protected $nextScript = null;
public function setNextResponse(Response $response)
{
$this->nextResponse = $response;
}
public function setNextScript($script)
{
$this->nextScript = $script;
}
protected function doRequest($request)
{
if (null === $this->nextResponse)
{
return new Response();
}
else
{
$response = $this->nextResponse;
$this->nextResponse = null;
return $response;
}
}
protected function getScript($request)
{
$r = new \ReflectionClass('Symfony\Components\BrowserKit\Response');
$path = $r->getFileName();
return <<<EOF
<?php
require_once('$path');
echo serialize($this->nextScript);
EOF;
}
}
class ClientTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers Symfony\Components\BrowserKit\Client::getHistory
*/
public function testGetHistory()
{
$client = new TestClient(array(), $history = new History());
$this->assertSame($history, $client->getHistory(), '->getHistory() returns the History');
}
/**
* @covers Symfony\Components\BrowserKit\Client::getCookieJar
*/
public function testGetCookieJar()
{
$client = new TestClient(array(), null, $cookieJar = new CookieJar());
$this->assertSame($cookieJar, $client->getCookieJar(), '->getCookieJar() returns the CookieJar');
}
/**
* @covers Symfony\Components\BrowserKit\Client::getRequest
*/
public function testGetRequest()
{
$client = new TestClient();
$client->request('GET', 'http://example.com/');
$this->assertEquals('http://example.com/', $client->getRequest()->getUri(), '->getCrawler() returns the Request of the last request');
}
/**
* @covers Symfony\Components\BrowserKit\Client::getResponse
*/
public function testGetResponse()
{
$client = new TestClient();
$client->setNextResponse(new Response('foo'));
$client->request('GET', 'http://example.com/');
$this->assertEquals('foo', $client->getResponse()->getContent(), '->getCrawler() returns the Response of the last request');
}
/**
* @covers Symfony\Components\BrowserKit\Client::getCrawler
*/
public function testGetCrawler()
{
$client = new TestClient();
$client->setNextResponse(new Response('foo'));
$crawler = $client->request('GET', 'http://example.com/');
$this->assertSame($crawler, $client->getCrawler(), '->getCrawler() returns the Crawler of the last request');
}
public function testRequestHttpHeaders()
{
$client = new TestClient();
$client->request('GET', '/');
$headers = $client->getRequest()->getServer();
$this->assertEquals('localhost', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header');
$client = new TestClient();
$client->request('GET', 'http://www.example.com');
$headers = $client->getRequest()->getServer();
$this->assertEquals('www.example.com', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header');
$client->request('GET', 'https://www.example.com');
$headers = $client->getRequest()->getServer();
$this->assertTrue($headers['HTTPS'], '->request() sets the HTTPS header');
}
public function testRequestURIConversion()
{
$client = new TestClient();
$client->request('GET', '/foo');
$this->assertEquals('http://localhost/foo', $client->getRequest()->getUri(), '->request() converts the URI to an absolute one');
$client = new TestClient();
$client->request('GET', 'http://www.example.com');
$this->assertEquals('http://www.example.com', $client->getRequest()->getUri(), '->request() does not change absolute URIs');
$client = new TestClient();
$client->request('GET', 'http://www.example.com/');
$client->request('GET', '/foo');
$this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo');
$client->request('GET', '#');
$this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #');
$client->request('GET', '#');
$this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #');
$client->request('GET', '#foo');
$this->assertEquals('http://www.example.com/foo#foo', $client->getRequest()->getUri(), '->request() uses the previous request for #');
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/');
$client->request('GET', 'bar');
$this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->request('GET', 'bar');
$this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
}
public function testRequestReferer()
{
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->request('GET', 'bar');
$server = $client->getRequest()->getServer();
$this->assertEquals('http://www.example.com/foo/foobar', $server['HTTP_REFERER'], '->request() sets the referer');
}
public function testRequestHistory()
{
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->request('GET', 'bar');
$this->assertEquals('http://www.example.com/foo/bar', $client->getHistory()->current()->getUri(), '->request() updates the History');
$this->assertEquals('http://www.example.com/foo/foobar', $client->getHistory()->back()->getUri(), '->request() updates the History');
}
public function testRequestCookies()
{
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->request('GET', 'bar');
RETURN;
$this->assertEquals('http://www.example.com/foo/bar', $client->getHistory()->current()->getUri(), '->request() updates the History');
$this->assertEquals('http://www.example.com/foo/foobar', $client->getHistory()->back()->getUri(), '->request() updates the History');
}
public function testClick()
{
$client = new TestClient();
$client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>'));
$crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
$client->click($crawler->filter('a')->link());
$this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() clicks on links');
}
public function testSubmit()
{
$client = new TestClient();
$client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
$crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
$client->submit($crawler->filter('input')->form());
$this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms');
}
public function testFollowRedirect()
{
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
try
{
$client->followRedirect();
$this->fail('->followRedirect() throws a \LogicException if the request was not redirected');
}
catch (\Exception $e)
{
$this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request was not redirected');
}
$client->setNextResponse(new Response('', 200, array('Location' => 'http://www.example.com/redirected')));
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->followRedirect();
$this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
}
public function testBack()
{
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->request('GET', 'http://www.example.com/foo');
$client->back();
$this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->back() goes back in the history');
}
public function testForward()
{
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->request('GET', 'http://www.example.com/foo');
$client->back();
$client->forward();
$this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->forward() goes forward in the history');
}
public function testReload()
{
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->reload();
$this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->forward() realoads the current page');
}
public function testRestart()
{
$client = new TestClient();
$client->request('GET', 'http://www.example.com/foo/foobar');
$client->restart();
$this->assertTrue($client->getHistory()->isEmpty(), '->restart() clears the history');
$this->assertEquals(array(), $client->getCookieJar()->all(), '->restart() clears the cookies');
}
public function testInsulatedRequests()
{
$client = new TestClient();
$client->insulate();
$client->setNextScript("new Symfony\Components\BrowserKit\Response('foobar')");
$client->request('GET', 'http://www.example.com/foo/foobar');
$this->assertEquals('foobar', $client->getResponse()->getContent(), '->insulate() process the request in a forked process');
$client->setNextScript("new Symfony\Components\BrowserKit\Response('foobar)");
try
{
$client->request('GET', 'http://www.example.com/foo/foobar');
$this->fail('->request() throws a \RuntimeException if the script has an error');
}
catch (\Exception $e)
{
$this->assertInstanceof('RuntimeException', $e, '->request() throws a \RuntimeException if the script has an error');
}
}
}

View File

@ -0,0 +1,98 @@
<?php
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Components\BrowserKit;
use Symfony\Components\BrowserKit\CookieJar;
use Symfony\Components\BrowserKit\Cookie;
use Symfony\Components\BrowserKit\Response;
class CookieJarTest extends \PHPUnit_Framework_TestCase
{
public function testSetGet()
{
$cookieJar = new CookieJar();
$cookieJar->set($cookie = new Cookie('foo', 'bar'));
$this->assertEquals($cookie, $cookieJar->get('foo'), '->set() sets a cookie');
$this->assertNull($cookieJar->get('foobar'), '->get() returns null if the cookie does not exist');
$cookieJar->set($cookie = new Cookie('foo', 'bar', time() - 86400));
$this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
}
public function testExpire()
{
$cookieJar = new CookieJar();
$cookieJar->set($cookie = new Cookie('foo', 'bar'));
$cookieJar->expire('foo');
$this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired');
}
public function testAll()
{
$cookieJar = new CookieJar();
$cookieJar->set($cookie1 = new Cookie('foo', 'bar'));
$cookieJar->set($cookie2 = new Cookie('bar', 'foo'));
$this->assertEquals(array('foo' => $cookie1, 'bar' => $cookie2), $cookieJar->all(), '->all() returns all cookies in the jar');
}
public function testClear()
{
$cookieJar = new CookieJar();
$cookieJar->set($cookie1 = new Cookie('foo', 'bar'));
$cookieJar->set($cookie2 = new Cookie('bar', 'foo'));
$cookieJar->clear();
$this->assertEquals(array(), $cookieJar->all(), '->clear() expires all cookies');
}
public function testUpdateFromResponse()
{
$response = new Response('', 200, array(), array('foo' => array('value' => 'foo')));
$cookieJar = new CookieJar();
$cookieJar->set(new Cookie('bar', 'bar'));
$cookieJar->updateFromResponse($response);
$this->assertEquals('foo', $cookieJar->get('foo')->getValue(), '->updateFromResponse() updates cookies from a Response objects');
$this->assertNull($cookieJar->get('bar'), '->updateFromResponse() updates cookies from a Response objects');
}
/**
* @dataProvider provideGetValuesValues
*/
public function testGetValues($uri, $values)
{
$cookieJar = new CookieJar();
$cookieJar->set($cookie1 = new Cookie('foo_nothing', 'foo'));
$cookieJar->set($cookie2 = new Cookie('foo_expired', 'foo', time() - 86400));
$cookieJar->set($cookie3 = new Cookie('foo_path', 'foo', 0, '/foo'));
$cookieJar->set($cookie4 = new Cookie('foo_domain', 'foo', 0, '/', 'example.com'));
$cookieJar->set($cookie5 = new Cookie('foo_secure', 'foo', 0, '/', '', true));
$this->assertEquals($values, array_keys($cookieJar->getValues($uri)), '->getValues() returns the cookie for a given URI');
}
public function provideGetValuesValues()
{
return array(
array('http://www.example.com/', array('foo_nothing', 'foo_domain')),
array('http://foo.example.com/', array('foo_nothing', 'foo_domain')),
array('http://foo.example1.com/', array('foo_nothing')),
array('https://foo.example.com/', array('foo_nothing', 'foo_domain', 'foo_secure')),
array('http://www.example.com/foo/bar', array('foo_nothing', 'foo_path', 'foo_domain')),
);
}
}

View File

@ -0,0 +1,71 @@
<?php
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Components\BrowserKit;
use Symfony\Components\BrowserKit\Cookie;
class CookieTest extends \PHPUnit_Framework_TestCase
{
public function testGetName()
{
$cookie = new Cookie('foo', 'bar');
$this->assertEquals('foo', $cookie->getName(), '->getName() returns the cookie name');
}
public function testGetValue()
{
$cookie = new Cookie('foo', 'bar');
$this->assertEquals('bar', $cookie->getValue(), '->getValue() returns the cookie value');
}
public function testGetPath()
{
$cookie = new Cookie('foo', 'bar', 0);
$this->assertEquals('/', $cookie->getPath(), '->getPath() returns / is no path is defined');
$cookie = new Cookie('foo', 'bar', 0, '/foo');
$this->assertEquals('/foo', $cookie->getPath(), '->getPath() returns the cookie path');
}
public function testGetDomain()
{
$cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com');
$this->assertEquals('foo.com', $cookie->getDomain(), '->getDomain() returns the cookie domain');
}
public function testIsSecure()
{
$cookie = new Cookie('foo', 'bar');
$this->assertFalse($cookie->isSecure(), '->isSecure() returns false if not defined');
$cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com', true);
$this->assertTrue($cookie->isSecure(), '->getDomain() returns the cookie secure flag');
}
public function testGetExpireTime()
{
$cookie = new Cookie('foo', 'bar');
$this->assertEquals(0, $cookie->getExpireTime(), '->getExpireTime() returns the expire time');
$cookie = new Cookie('foo', 'bar', $time = time() - 86400);
$this->assertEquals($time, $cookie->getExpireTime(), '->getExpireTime() returns the expire time');
}
public function testIsExpired()
{
$cookie = new Cookie('foo', 'bar');
$this->assertFalse($cookie->isExpired(), '->isExpired() returns false when the cookie never expires (0 as expire time)');
$cookie = new Cookie('foo', 'bar', time() - 86400);
$this->assertTrue($cookie->isExpired(), '->isExpired() returns true when the cookie is expired');
}
}

View File

@ -0,0 +1,110 @@
<?php
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Components\BrowserKit;
use Symfony\Components\BrowserKit\History;
use Symfony\Components\BrowserKit\Request;
class HistoryTest extends \PHPUnit_Framework_TestCase
{
public function testAdd()
{
$history = new History();
$history->add(new Request('http://www.example1.com/', 'get'));
$this->assertSame('http://www.example1.com/', $history->current()->getUri(), '->add() adds a request to the history');
$history->add(new Request('http://www.example2.com/', 'get'));
$this->assertSame('http://www.example2.com/', $history->current()->getUri(), '->add() adds a request to the history');
$history->add(new Request('http://www.example3.com/', 'get'));
$history->back();
$history->add(new Request('http://www.example4.com/', 'get'));
$this->assertSame('http://www.example4.com/', $history->current()->getUri(), '->add() adds a request to the history');
$history->back();
$this->assertSame('http://www.example2.com/', $history->current()->getUri(), '->add() adds a request to the history');
}
public function testClearIsEmpty()
{
$history = new History();
$history->add(new Request('http://www.example.com/', 'get'));
$this->assertFalse($history->isEmpty(), '->isEmpty() returns false if the history is not empty');
$history->clear();
$this->assertTrue($history->isEmpty(), '->isEmpty() true if the history is empty');
}
public function testCurrent()
{
$history = new History();
try
{
$history->current();
$this->fail('->current() throws a \LogicException if the history is empty');
}
catch (\Exception $e)
{
$this->assertInstanceof('LogicException', $e, '->current() throws a \LogicException if the history is empty');
}
$history->add(new Request('http://www.example.com/', 'get'));
$this->assertSame('http://www.example.com/', $history->current()->getUri(), '->current() returns the current request in the history');
}
public function testBack()
{
$history = new History();
$history->add(new Request('http://www.example.com/', 'get'));
try
{
$history->back();
$this->fail('->back() throws a \LogicException if the history is already on the first page');
}
catch (\Exception $e)
{
$this->assertInstanceof('LogicException', $e, '->current() throws a \LogicException if the history is already on the first page');
}
$history->add(new Request('http://www.example1.com/', 'get'));
$history->back();
$this->assertSame('http://www.example.com/', $history->current()->getUri(), '->back() returns the previous request in the history');
}
public function testForward()
{
$history = new History();
$history->add(new Request('http://www.example.com/', 'get'));
$history->add(new Request('http://www.example1.com/', 'get'));
try
{
$history->forward();
$this->fail('->forward() throws a \LogicException if the history is already on the last page');
}
catch (\Exception $e)
{
$this->assertInstanceof('LogicException', $e, '->forward() throws a \LogicException if the history is already on the last page');
}
$history->back();
$history->forward();
$this->assertSame('http://www.example1.com/', $history->current()->getUri(), '->forward() returns the next request in the history');
}
}

View File

@ -0,0 +1,53 @@
<?php
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Components\BrowserKit;
use Symfony\Components\BrowserKit\Request;
class RequestTest extends \PHPUnit_Framework_TestCase
{
public function testGetUri()
{
$request = new Request('http://www.example.com/', 'get');
$this->assertEquals('http://www.example.com/', $request->getUri(), '->getUri() returns the URI of the request');
}
public function testGetMethod()
{
$request = new Request('http://www.example.com/', 'get');
$this->assertEquals('get', $request->getMethod(), '->getMethod() returns the method of the request');
}
public function testGetParameters()
{
$request = new Request('http://www.example.com/', 'get', array('foo' => 'bar'));
$this->assertEquals(array('foo' => 'bar'), $request->getParameters(), '->getParameters() returns the parameters of the request');
}
public function testGetFiles()
{
$request = new Request('http://www.example.com/', 'get', array(), array('foo' => 'bar'));
$this->assertEquals(array('foo' => 'bar'), $request->getFiles(), '->getFiles() returns the uploaded files of the request');
}
public function testGetCookies()
{
$request = new Request('http://www.example.com/', 'get', array(), array(), array('foo' => 'bar'));
$this->assertEquals(array('foo' => 'bar'), $request->getCookies(), '->getCookies() returns the cookies of the request');
}
public function testGetServer()
{
$request = new Request('http://www.example.com/', 'get', array(), array(), array(), array('foo' => 'bar'));
$this->assertEquals(array('foo' => 'bar'), $request->getServer(), '->getServer() returns the server parameters of the request');
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Components\BrowserKit;
use Symfony\Components\BrowserKit\Response;
class ResponseTest extends \PHPUnit_Framework_TestCase
{
public function testGetUri()
{
$response = new Response('foo');
$this->assertEquals('foo', $response->getContent(), '->getContent() returns the content of the response');
}
public function testGetStatus()
{
$response = new Response('foo', 304);
$this->assertEquals('304', $response->getStatus(), '->getStatus() returns the status of the response');
}
public function testGetHeaders()
{
$response = new Response('foo', 304, array('foo' => 'bar'));
$this->assertEquals(array('foo' => 'bar'), $response->getHeaders(), '->getHeaders() returns the headers of the response');
}
public function testGetHeader()
{
$response = new Response('foo', 304, array('Content-Type' => 'text/html'));
$this->assertEquals('text/html', $response->getHeader('Content-Type'), '->getHeader() returns a header of the response');
$this->assertEquals('text/html', $response->getHeader('content-type'), '->getHeader() returns a header of the response');
$this->assertEquals('text/html', $response->getHeader('content_type'), '->getHeader() returns a header of the response');
$this->assertNull($response->getHeader('foo'), '->getHeader() returns null if the header is not defined');
}
public function testGetCookies()
{
$response = new Response('foo', 304, array(), array('foo' => 'bar'));
$this->assertEquals(array('foo' => 'bar'), $response->getCookies(), '->getCookies() returns the cookies of the response');
}
}