123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544 |
- <?php
- require_once(dirname(__FILE__).'/../vendor/lime/lime.php');
- /*
- * This file is part of the symfony package.
- * (c) 2004-2006 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.
- */
- /**
- * sfTestBrowser simulates a fake browser which can test a symfony application.
- *
- * @package symfony
- * @subpackage test
- * @author Fabien Potencier <fabien.potencier@symfony-project.com>
- * @version SVN: $Id: sfTestBrowser.class.php 16170 2009-03-11 08:02:42Z fabien $
- */
- class sfTestBrowser extends sfBrowser
- {
- protected static
- $test = null;
- /**
- * Initializes the browser tester instance.
- *
- * @param string $hostname Hostname
- * @param string $remote Remote IP address
- * @param array $options Options
- */
- public function initialize($hostname = null, $remote = null, $options = array())
- {
- parent::initialize($hostname, $remote, $options);
- $output = isset($options['output']) ? $options['output'] : new lime_output_color();
- if (is_null(self::$test))
- {
- self::$test = new lime_test(null, $output);
- }
- }
- /**
- * Retrieves the lime_test instance.
- *
- * @return lime_test The lime_test instance
- */
- public function test()
- {
- return self::$test;
- }
- /**
- * Retrieves and checks an action.
- *
- * @param string $module Module name
- * @param string $action Action name
- * @param string $url Url
- * @param string $code The expected return status code
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function getAndCheck($module, $action, $url = null, $code = 200)
- {
- return $this->
- get(null !== $url ? $url : sprintf('/%s/%s', $module, $action))->
- isStatusCode($code)->
- isRequestParameter('module', $module)->
- isRequestParameter('action', $action)
- ;
- }
- /**
- * Calls a request.
- *
- * @param string $uri URI to be invoked
- * @param string $method HTTP method used
- * @param array $parameters Additional paramaters
- * @param bool $changeStack If set to false ActionStack is not changed
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function call($uri, $method = 'get', $parameters = array(), $changeStack = true)
- {
- $uri = $this->fixUri($uri);
- $this->test()->comment(sprintf('%s %s', strtolower($method), $uri));
- return parent::call($uri, $method, $parameters, $changeStack);
- }
- /**
- * Simulates the browser back button.
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function back()
- {
- $this->test()->comment('back');
- return parent::back();
- }
- /**
- * Simulates the browser forward button.
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function forward()
- {
- $this->test()->comment('forward');
- return parent::forward();
- }
- /**
- * Tests if the current request has been redirected.
- *
- * @param bool $boolean Flag for redirection mode
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isRedirected($boolean = true)
- {
- if ($location = $this->context->getResponse()->getHttpHeader('location'))
- {
- $boolean ? $this->test()->pass(sprintf('page redirected to "%s"', $location)) : $this->test()->fail(sprintf('page redirected to "%s"', $location));
- }
- else
- {
- $boolean ? $this->test()->fail('page redirected') : $this->test()->pass('page not redirected');
- }
- return $this;
- }
- /**
- * Checks that the current response contains a given text.
- *
- * @param string $uri Uniform resource identifier
- * @param string $text Text in the response
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function check($uri, $text = null)
- {
- $this->get($uri)->isStatusCode();
- if ($text !== null)
- {
- $this->responseContains($text);
- }
- return $this;
- }
- /**
- * Test an status code for the current test browser.
- *
- * @param string Status code to check, default 200
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isStatusCode($statusCode = 200)
- {
- $this->test()->is($this->getResponse()->getStatusCode(), $statusCode, sprintf('status code is "%s"', $statusCode));
- return $this;
- }
- /**
- * Tests whether or not a given string is in the response.
- *
- * @param string Text to check
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function responseContains($text)
- {
- $this->test()->like($this->getResponse()->getContent(), '/'.preg_quote($text, '/').'/', sprintf('response contains "%s"', substr($text, 0, 40)));
- return $this;
- }
- /**
- * Tests whether or not a given key and value exists in the current request.
- *
- * @param string $key
- * @param string $value
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isRequestParameter($key, $value)
- {
- $this->test()->is($this->getRequest()->getParameter($key), $value, sprintf('request parameter "%s" is "%s"', $key, $value));
- return $this;
- }
- /**
- * Checks that the request is forwarded to a given module/action.
- *
- * @param string $moduleName The module name
- * @param string $actionName The action name
- * @param mixed $position The position in the action stack (default to the last entry)
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isForwardedTo($moduleName, $actionName, $position = 'last')
- {
- $actionStack = $this->context->getActionStack();
- switch ($position)
- {
- case 'first':
- $entry = $actionStack->getFirstEntry();
- break;
- case 'last':
- $entry = $actionStack->getLastEntry();
- break;
- default:
- $entry = $actionStack->getEntry($position);
- }
- $this->test()->is($entry->getModuleName(), $moduleName, sprintf('request is forwarded to the "%s" module (%s)', $moduleName, $position));
- $this->test()->is($entry->getActionName(), $actionName, sprintf('request is forwarded to the "%s" action (%s)', $actionName, $position));
- return $this;
- }
- /**
- * Tests for a response header.
- *
- * @param string $key
- * @param string $value
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isResponseHeader($key, $value)
- {
- $headers = explode(', ', $this->getResponse()->getHttpHeader($key));
- $ok = false;
- foreach ($headers as $header)
- {
- if ($header == $value)
- {
- $ok = true;
- break;
- }
- }
- $this->test()->ok($ok, sprintf('response header "%s" is "%s" (%s)', $key, $value, $this->getResponse()->getHttpHeader($key)));
- return $this;
- }
- /**
- * Tests for the user culture.
- *
- * @param string $culture The user culture
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isUserCulture($culture)
- {
- $this->test()->is($this->getContext()->getUser()->getCulture(), $culture, sprintf('user culture is "%s"', $culture));
- return $this;
- }
- /**
- * Tests for the request is in the given format.
- *
- * @param string $format The request format
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isRequestFormat($format)
- {
- $this->test()->is($this->getContext()->getRequest()->getRequestFormat(), $format, sprintf('request format is "%s"', $format));
- return $this;
- }
- /**
- * Tests that the current response matches a given CSS selector.
- *
- * @param string $selector The response selector or a sfDomCssSelector object
- * @param mixed $value Flag for the selector
- * @param array $options Options for the current test
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function checkResponseElement($selector, $value = true, $options = array())
- {
- if (is_object($selector))
- {
- $values = $selector->getValues();
- }
- else
- {
- $values = $this->getResponseDomCssSelector()->matchAll($selector)->getValues();
- }
- if (false === $value)
- {
- $this->test()->is(count($values), 0, sprintf('response selector "%s" does not exist', $selector));
- }
- else if (true === $value)
- {
- $this->test()->cmp_ok(count($values), '>', 0, sprintf('response selector "%s" exists', $selector));
- }
- else if (is_int($value))
- {
- $this->test()->is(count($values), $value, sprintf('response selector "%s" matches "%s" times', $selector, $value));
- }
- else if (preg_match('/^(!)?([^a-zA-Z0-9\\\\]).+?\\2[ims]?$/', $value, $match))
- {
- $position = isset($options['position']) ? $options['position'] : 0;
- if ($match[1] == '!')
- {
- $this->test()->unlike(@$values[$position], substr($value, 1), sprintf('response selector "%s" does not match regex "%s"', $selector, substr($value, 1)));
- }
- else
- {
- $this->test()->like(@$values[$position], $value, sprintf('response selector "%s" matches regex "%s"', $selector, $value));
- }
- }
- else
- {
- $position = isset($options['position']) ? $options['position'] : 0;
- $this->test()->is(@$values[$position], $value, sprintf('response selector "%s" matches "%s"', $selector, $value));
- }
- if (isset($options['count']))
- {
- $this->test()->is(count($values), $options['count'], sprintf('response selector "%s" matches "%s" times', $selector, $options['count']));
- }
- return $this;
- }
- /**
- * Tests if an exception is thrown by the latest request.
- *
- * @param string $class Class name
- * @param string $message Message name
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function throwsException($class = null, $message = null)
- {
- $e = $this->getCurrentException();
- if (null === $e)
- {
- $this->test()->fail('response returns an exception');
- }
- else
- {
- if (null !== $class)
- {
- $this->test()->ok($e instanceof $class, sprintf('response returns an exception of class "%s"', $class));
- }
- else
- {
- $lime = null;
- }
- if (null !== $message && preg_match('/^(!)?([^a-zA-Z0-9\\\\]).+?\\2[ims]?$/', $message, $match))
- {
- if ($match[1] == '!')
- {
- $this->test()->unlike($e->getMessage(), substr($message, 1), sprintf('response exception message does not match regex "%s"', $message));
- }
- else
- {
- $this->test()->like($e->getMessage(), $message, sprintf('response exception message matches regex "%s"', $message));
- }
- }
- else if (null !== $message)
- {
- $this->test()->is($e->getMessage(), $message, sprintf('response exception message matches regex "%s"', $message));
- }
- }
- $this->resetCurrentException();
- return $this;
- }
-
- /**
- * Trigger a test failure if an uncaught exception is present.
- *
- * @return bool
- */
- public function checkCurrentExceptionIsEmpty()
- {
- if (false === ($empty = parent::checkCurrentExceptionIsEmpty()))
- {
- $this->test()->fail(sprintf('last request threw an uncaught exception "%s: %s"', get_class($this->getCurrentException()), $this->getCurrentException()->getMessage()));
- }
-
- return $empty;
- }
- /**
- * Tests if the given uri is cached.
- *
- * @param boolean $boolean Flag for checking the cache
- * @param boolean $with_layout If have or not layout
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isCached($boolean, $with_layout = false)
- {
- return $this->isUriCached($this->context->getRouting()->getCurrentInternalUri(), $boolean, $with_layout);
- }
- /**
- * Tests if the given uri is cached.
- *
- * @param string $uri Uniform resource identifier
- * @param boolean $boolean Flag for checking the cache
- * @param boolean $with_layout If have or not layout
- *
- * @return sfTestBrowser The current sfTestBrowser instance
- */
- public function isUriCached($uri, $boolean, $with_layout = false)
- {
- $cacheManager = $this->context->getViewCacheManager();
- // check that cache is enabled
- if (!$cacheManager)
- {
- $this->test()->ok(!$boolean, 'cache is disabled');
- return $this;
- }
- if ($uri == $this->context->getRouting()->getCurrentInternalUri())
- {
- $main = true;
- $type = $with_layout ? 'page' : 'action';
- }
- else
- {
- $main = false;
- $type = $uri;
- }
- // check layout configuration
- if ($cacheManager->withLayout($uri) && !$with_layout)
- {
- $this->test()->fail('cache without layout');
- $this->test()->skip('cache is not configured properly', 2);
- }
- else if (!$cacheManager->withLayout($uri) && $with_layout)
- {
- $this->test()->fail('cache with layout');
- $this->test()->skip('cache is not configured properly', 2);
- }
- else
- {
- $this->test()->pass('cache is configured properly');
- // check page is cached
- $ret = $this->test()->is($cacheManager->has($uri), $boolean, sprintf('"%s" %s in cache', $type, $boolean ? 'is' : 'is not'));
- // check that the content is ok in cache
- if ($boolean)
- {
- if (!$ret)
- {
- $this->test()->fail('content in cache is ok');
- }
- else if ($with_layout)
- {
- $response = unserialize($cacheManager->get($uri));
- $content = $response->getContent();
- $this->test()->ok($content == $this->getResponse()->getContent(), 'content in cache is ok');
- }
- else
- {
- $ret = unserialize($cacheManager->get($uri));
- $content = $ret['content'];
- $this->test()->ok(false !== strpos($this->getResponse()->getContent(), $content), 'content in cache is ok');
- }
- }
- }
- return $this;
- }
- }
- if (!defined('E_RECOVERABLE_ERROR'))
- {
- define('E_RECOVERABLE_ERROR', 4096);
- }
- /**
- * Error handler for the current test browser instance.
- *
- * @param mixed $errno Error number
- * @param string $errstr Error message
- * @param string $errfile Error file
- * @param mixed $errline Error line
- */
- function sfTestBrowserErrorHandler($errno, $errstr, $errfile, $errline)
- {
- if (($errno & error_reporting()) == 0)
- {
- return false;
- }
- $msg = sprintf('PHP sent a "%%s" error at %s line %s (%s)', $errfile, $errline, $errstr);
- switch ($errno)
- {
- case E_WARNING:
- $msg = sprintf($msg, 'warning');
- throw new Exception($msg);
- break;
- case E_NOTICE:
- $msg = sprintf($msg, 'notice');
- throw new Exception($msg);
- break;
- case E_STRICT:
- $msg = sprintf($msg, 'strict');
- throw new Exception($msg);
- break;
- case E_RECOVERABLE_ERROR:
- $msg = sprintf($msg, 'catchable');
- throw new Exception($msg);
- break;
- }
- return false;
- }
- set_error_handler('sfTestBrowserErrorHandler');
|