Development

Changeset 11116

You must first sign up to be able to contribute.

Changeset 11116

Show
Ignore:
Timestamp:
08/25/08 17:20:48 (10 months ago)
Author:
fabien
Message:

[1.2] refactored browser and functional test classes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/1.2/UPGRADE_TO_1_2

    r11102 r11116  
    327327(we used to compute it with `sfConfig::get('sf_time_start')`, which does not exist anymore). 
    328328This means that the time displayed will be much larger than in symfony 1.0 and 1.1. 
     329 
     330Browser 
     331------- 
     332 
     333The `sfBrowser` and `sfTestBrowser` classes have been refactored in four classes: 
     334 
     335  * `sfBrowserBase`:        The base browser class. It knows nothing about symfony, 
     336                            except classes from the symfony platform. 
     337 
     338  * `sfBrowser`:            It inherits from `sfBrowserBase` and implements the 
     339                            methods specific to symfony. 
     340 
     341  * `sfTestFunctionalBase`: The base functional test class. It implements test 
     342                            methods that are independant from symfony. 
     343 
     344  * `sfTestFunctional`:     It inherits from `sfTestFunctionalBase` and implements 
     345                            the test methods specific to symfony. 
     346 
     347  * `sfTestBrowser`:        A BC class which is the same as the `sfTestFunctional` 
     348                            class with a constructor signature compatible with symfony 1.1 
     349 
     350The idea behind the refactor is that the `sfTestFunctional` class is a test class, 
     351not a browser. So, it takes a browser and a test object as its arguments: 
     352 
     353    [php] 
     354    $testBrowser = new sfTestBrowser('localhost'); 
     355 
     356    $tester = new sfTestFunctional(new sfBrowser('localhost'), new lime_test()); 
     357 
     358The `sfTestFunctional` class acts as a proxy for the browser class which means 
     359that all methods from the browser are accessible directly from the tester object. 
     360 
     361This refactor must not introduce backward incompatibility with symfony 1.1. 
  • branches/1.2/lib/autoload/sfCoreAutoload.class.php

    r11041 r11116  
    363363  'sfTestUnitTask' => 'task/test', 
    364364  'sfTestBrowser' => 'test', 
     365  'sfTestFunctional' => 'test', 
     366  'sfTestFunctionalBase' => 'test', 
    365367  'sfBasicSecurityUser' => 'user', 
    366368  'sfSecurityUser' => 'user', 
    367369  'sfUser' => 'user', 
    368370  'sfBrowser' => 'util', 
     371  'sfBrowserBase' => 'util', 
    369372  'sfCallable' => 'util', 
    370373  'sfContext' => 'util', 
  • branches/1.2/lib/test/sfTestBrowser.class.php

    r10830 r11116  
    1212 
    1313/** 
    14  * sfTestBrowser simulates a fake browser which can test a symfony application. 
     14 * sfTestBrowser simulates a browser which can test a symfony application. 
     15 * 
     16 * sfTestFunctional is backward compatible class for symfony 1.0, and 1.1. 
     17 * For new code, you can use the sfTestFunctional class directly. 
    1518 * 
    1619 * @package    symfony 
     
    1922 * @version    SVN: $Id$ 
    2023 */ 
    21 class sfTestBrowser extends sfBrowser 
     24class sfTestBrowser extends sfTestFunctional 
    2225{ 
    23   protected static 
    24     $test = null; 
    25  
    2626  /** 
    2727   * Initializes the browser tester instance. 
    2828   * 
    29    * @param string $hostname  Hostname 
    30    * @param string $remote    Remote IP address 
    31    * @param array  $options   Options 
     29   * @param string $hostname  Hostname to browse 
     30   * @param string $remote    Remote address to spook 
     31   * @param array  $options   Options for sfBrowser 
    3232   */ 
    33   public function initialize($hostname = null, $remote = null, $options = array()) 
     33  public function __construct($hostname = null, $remote = null, $options = array()) 
    3434  { 
    35     parent::initialize($hostname, $remote, $options); 
    36  
    37     $output = isset($options['output']) ? $options['output'] : new lime_output_color(); 
    38  
    39     if (is_null(self::$test)) 
     35    if (is_object($hostname)) 
    4036    { 
    41       self::$test = new lime_test(null, $output); 
    42     } 
    43   } 
    44  
    45   /** 
    46    * Retrieves the lime_test instance. 
    47    * 
    48    * @return lime_test The lime_test instance 
    49    */ 
    50   public function test() 
    51   { 
    52     return self::$test; 
    53   } 
    54  
    55   /** 
    56    * Retrieves and checks an action. 
    57    * 
    58    * @param  string $module  Module name 
    59    * @param  string $action  Action name 
    60    * @param  string $url     Url 
    61    * @param  string $code    The expected return status code 
    62    * 
    63    * @return sfTestBrowser The current sfTestBrowser instance 
    64    */ 
    65   public function getAndCheck($module, $action, $url = null, $code = 200) 
    66   { 
    67     return $this-> 
    68       get(null !== $url ? $url : sprintf('/%s/%s', $module, $action))-> 
    69       isStatusCode($code)-> 
    70       isRequestParameter('module', $module)-> 
    71       isRequestParameter('action', $action) 
    72     ; 
    73   } 
    74  
    75   /** 
    76    * Calls a request. 
    77    * 
    78    * @param  string $uri          URI to be invoked 
    79    * @param  string $method       HTTP method used 
    80    * @param  array  $parameters   Additional paramaters 
    81    * @param  bool   $changeStack  If set to false ActionStack is not changed 
    82    * 
    83    * @return sfTestBrowser The current sfTestBrowser instance 
    84    */ 
    85   public function call($uri, $method = 'get', $parameters = array(), $changeStack = true) 
    86   { 
    87     $uri = $this->fixUri($uri); 
    88  
    89     $this->test()->comment(sprintf('%s %s', strtolower($method), $uri)); 
    90  
    91     return parent::call($uri, $method, $parameters, $changeStack); 
    92   } 
    93  
    94   /** 
    95    * Simulates the browser back button. 
    96    * 
    97    * @return sfTestBrowser The current sfTestBrowser instance 
    98    */ 
    99   public function back() 
    100   { 
    101     $this->test()->comment('back'); 
    102  
    103     return parent::back(); 
    104   } 
    105  
    106   /** 
    107    * Simulates the browser forward button. 
    108    * 
    109    * @return sfTestBrowser The current sfTestBrowser instance 
    110    */ 
    111   public function forward() 
    112   { 
    113     $this->test()->comment('forward'); 
    114  
    115     return parent::forward(); 
    116   } 
    117  
    118   /** 
    119    * Tests if the current request has been redirected. 
    120    * 
    121    * @param  bool $boolean  Flag for redirection mode 
    122    * 
    123    * @return sfTestBrowser The current sfTestBrowser instance 
    124    */ 
    125   public function isRedirected($boolean = true) 
    126   { 
    127     if ($location = $this->context->getResponse()->getHttpHeader('location')) 
    128     { 
    129       $boolean ? $this->test()->pass(sprintf('page redirected to "%s"', $location)) : $this->test()->fail(sprintf('page redirected to "%s"', $location)); 
     37      // new signature 
     38      parent::__construct($hostname, $remote); 
    13039    } 
    13140    else 
    13241    { 
    133       $boolean ? $this->test()->fail('page redirected') : $this->test()->pass('page not redirected'); 
    134     } 
     42      $browser = new sfBrowser($hostname, $remote, $options); 
    13543 
    136     return $this; 
    137   } 
    138  
    139   /** 
    140    * Checks that the current response contains a given text. 
    141    * 
    142    * @param  string $uri   Uniform resource identifier 
    143    * @param  string $text  Text in the response 
    144    * 
    145    * @return sfTestBrowser The current sfTestBrowser instance 
    146    */ 
    147   public function check($uri, $text = null) 
    148   { 
    149     $this->get($uri)->isStatusCode(); 
    150  
    151     if ($text !== null) 
    152     { 
    153       $this->responseContains($text); 
    154     } 
    155  
    156     return $this; 
    157   } 
    158  
    159   /** 
    160    * Test an status code for the current test browser. 
    161    * 
    162    * @param string Status code to check, default 200 
    163    * 
    164    * @return sfTestBrowser The current sfTestBrowser instance 
    165    */ 
    166   public function isStatusCode($statusCode = 200) 
    167   { 
    168     $this->test()->is($this->getResponse()->getStatusCode(), $statusCode, sprintf('status code is "%s"', $statusCode)); 
    169  
    170     return $this; 
    171   } 
    172  
    173   /** 
    174    * Tests whether or not a given string is in the response. 
    175    * 
    176    * @param string Text to check 
    177    * 
    178    * @return sfTestBrowser The current sfTestBrowser instance 
    179    */ 
    180   public function responseContains($text) 
    181   { 
    182     $this->test()->like($this->getResponse()->getContent(), '/'.preg_quote($text, '/').'/', sprintf('response contains "%s"', substr($text, 0, 40))); 
    183  
    184     return $this; 
    185   } 
    186  
    187   /** 
    188    * Tests whether or not a given key and value exists in the current request. 
    189    * 
    190    * @param string $key 
    191    * @param string $value 
    192    * 
    193    * @return sfTestBrowser The current sfTestBrowser instance 
    194    */ 
    195   public function isRequestParameter($key, $value) 
    196   { 
    197     $this->test()->is($this->getRequest()->getParameter($key), $value, sprintf('request parameter "%s" is "%s"', $key, $value)); 
    198  
    199     return $this; 
    200   } 
    201  
    202   /** 
    203    * Checks that the request is forwarded to a given module/action. 
    204    * 
    205    * @param  string $moduleName  The module name 
    206    * @param  string $actionName  The action name 
    207    * @param  mixed  $position    The position in the action stack (default to the last entry) 
    208    * 
    209    * @return sfTestBrowser The current sfTestBrowser instance 
    210    */ 
    211   public function isForwardedTo($moduleName, $actionName, $position = 'last') 
    212   { 
    213     $actionStack = $this->context->getActionStack(); 
    214  
    215     switch ($position) 
    216     { 
    217       case 'first': 
    218         $entry = $actionStack->getFirstEntry(); 
    219         break; 
    220       case 'last': 
    221         $entry = $actionStack->getLastEntry(); 
    222         break; 
    223       default: 
    224         $entry = $actionStack->getEntry($position); 
    225     } 
    226  
    227     $this->test()->is($entry->getModuleName(), $moduleName, sprintf('request is forwarded to the "%s" module (%s)', $moduleName, $position)); 
    228     $this->test()->is($entry->getActionName(), $actionName, sprintf('request is forwarded to the "%s" action (%s)', $actionName, $position)); 
    229  
    230     return $this; 
    231   } 
    232  
    233   /** 
    234    * Tests for a response header. 
    235    * 
    236    * @param  string $key 
    237    * @param  string $value 
    238    * 
    239    * @return sfTestBrowser The current sfTestBrowser instance 
    240    */ 
    241   public function isResponseHeader($key, $value) 
    242   { 
    243     $headers = explode(', ', $this->getResponse()->getHttpHeader($key)); 
    244  
    245     $ok = false; 
    246  
    247     foreach ($headers as $header) 
    248     { 
    249       if ($header == $value) 
     44      if (is_null(self::$test)) 
    25045      { 
    251         $ok = true; 
    252         break; 
    253       } 
    254     } 
    255  
    256     $this->test()->ok($ok, sprintf('response header "%s" is "%s" (%s)', $key, $value, $this->getResponse()->getHttpHeader($key))); 
    257  
    258     return $this; 
    259   } 
    260  
    261   /** 
    262    * Tests for the user culture. 
    263    * 
    264    * @param  string $culture  The user culture 
    265    * 
    266    * @return sfTestBrowser The current sfTestBrowser instance 
    267    */ 
    268   public function isUserCulture($culture) 
    269   { 
    270     $this->test()->is($this->getContext()->getUser()->getCulture(), $culture, sprintf('user culture is "%s"', $culture)); 
    271  
    272     return $this; 
    273   } 
    274  
    275   /** 
    276    * Tests for the request is in the given format. 
    277    * 
    278    * @param  string $format  The request format 
    279    * 
    280    * @return sfTestBrowser The current sfTestBrowser instance 
    281    */ 
    282   public function isRequestFormat($format) 
    283   { 
    284     $this->test()->is($this->getContext()->getRequest()->getRequestFormat(), $format, sprintf('request format is "%s"', $format)); 
    285  
    286     return $this; 
    287   } 
    288  
    289   /** 
    290    * Tests that the current response matches a given CSS selector. 
    291    * 
    292    * @param  string $selector  The response selector or a sfDomCssSelector object 
    293    * @param  mixed  $value     Flag for the selector 
    294    * @param  array  $options   Options for the current test 
    295    * 
    296    * @return sfTestBrowser The current sfTestBrowser instance 
    297    */ 
    298   public function checkResponseElement($selector, $value = true, $options = array()) 
    299   { 
    300     if (is_object($selector)) 
    301     { 
    302       $values = $selector->getValues(); 
    303     } 
    304     else 
    305     { 
    306       $values = $this->getResponseDomCssSelector()->matchAll($selector)->getValues(); 
    307     } 
    308  
    309     if (false === $value) 
    310     { 
    311       $this->test()->is(count($values), 0, sprintf('response selector "%s" does not exist', $selector)); 
    312     } 
    313     else if (true === $value) 
    314     { 
    315       $this->test()->cmp_ok(count($values), '>', 0, sprintf('response selector "%s" exists', $selector)); 
    316     } 
    317     else if (is_int($value)) 
    318     { 
    319       $this->test()->is(count($values), $value, sprintf('response selector "%s" matches "%s" times', $selector, $value)); 
    320     } 
    321     else if (preg_match('/^(!)?([^a-zA-Z0-9\\\\]).+?\\2[ims]?$/', $value, $match)) 
    322     { 
    323       $position = isset($options['position']) ? $options['position'] : 0; 
    324       if ($match[1] == '!') 
    325       { 
    326         $this->test()->unlike(@$values[$position], substr($value, 1), sprintf('response selector "%s" does not match regex "%s"', $selector, substr($value, 1))); 
    327       } 
    328       else 
    329       { 
    330         $this->test()->like(@$values[$position], $value, sprintf('response selector "%s" matches regex "%s"', $selector, $value)); 
    331       } 
    332     } 
    333     else 
    334     { 
    335       $position = isset($options['position']) ? $options['position'] : 0; 
    336       $this->test()->is(@$values[$position], $value, sprintf('response selector "%s" matches "%s"', $selector, $value)); 
    337     } 
    338  
    339     if (isset($options['count'])) 
    340     { 
    341       $this->test()->is(count($values), $options['count'], sprintf('response selector "%s" matches "%s" times', $selector, $options['count'])); 
    342     } 
    343  
    344     return $this; 
    345   } 
    346  
    347   /** 
    348    * Tests if an exception is thrown by the latest request. 
    349    * 
    350    * @param  string $class    Class name 
    351    * @param  string $message  Message name 
    352    * 
    353    * @return sfTestBrowser The current sfTestBrowser instance 
    354    */ 
    355   public function throwsException($class = null, $message = null) 
    356   { 
    357     $e = $this->getCurrentException(); 
    358  
    359     if (null === $e) 
    360     { 
    361       $this->test()->fail('response returns an exception'); 
    362     } 
    363     else 
    364     { 
    365       if (null !== $class) 
    366       { 
    367         $this->test()->ok($e instanceof $class, sprintf('response returns an exception of class "%s"', $class)); 
     46        $lime = new lime_test(null, isset($options['output']) ? $options['output'] : new lime_output_color()); 
    36847      } 
    36948 
    370       if (null !== $message && preg_match('/^(!)?([^a-zA-Z0-9\\\\]).+?\\2[ims]?$/', $message, $match)) 
    371       { 
    372         if ($match[1] == '!') 
    373         { 
    374           $this->test()->unlike($e->getMessage(), substr($message, 1), sprintf('response exception message does not match regex "%s"', $message)); 
    375         } 
    376         else 
    377         { 
    378           $this->test()->like($e->getMessage(), $message, sprintf('response exception message matches regex "%s"', $message)); 
    379         } 
    380       } 
    381       else if (null !== $message) 
    382       { 
    383         $this->test()->is($e->getMessage(), $message, sprintf('response exception message is "%s"', $message)); 
    384       } 
     49      parent::__construct($browser, $lime); 
    38550    } 
    386  
    387     $this->resetCurrentException(); 
    388  
    389     return $this; 
    390   } 
    391    
    392   /** 
    393    * Triggers a test failure if an uncaught exception is present. 
    394    *  
    395    * @return  bool 
    396    */ 
    397   public function checkCurrentExceptionIsEmpty() 
    398   { 
    399     if (false === ($empty = parent::checkCurrentExceptionIsEmpty())) 
    400     { 
    401       $this->test()->fail(sprintf('last request threw an uncaught exception "%s: %s"', get_class($this->getCurrentException()), $this->getCurrentException()->getMessage())); 
    402     } 
    403  
    404     return $empty; 
    405   } 
    406  
    407   /** 
    408    * Checks if a cookie exists. 
    409    * 
    410    * @param string  $name   The cookie name 
    411    * @param Boolean $exists Whether the cookie must exist or not 
    412    * 
    413    * @return sfTestBrowser The current sfTestBrowser instance 
    414    */ 
    415   public function hasCookie($name, $exists = true) 
    416   { 
    417     if (!array_key_exists($name, $_COOKIE)) 
    418     { 
    419       if ($exists) 
    420       { 
    421         $this->test()->fail(sprintf('cookie "%s" exist.', $name)); 
    422       } 
    423       else 
    424       { 
    425         $this->test()->pass(sprintf('cookie "%s" does not exist.', $name)); 
    426       } 
    427  
    428       return $this; 
    429     } 
    430  
    431     if ($exists) 
    432     { 
    433       $this->test()->pass(sprintf('cookie "%s" exists.', $name)); 
    434     } 
    435     else 
    436     { 
    437       $this->test()->fail(sprintf('cookie "%s" does not exist.', $name)); 
    438     } 
    439  
    440     return $this; 
    441   } 
    442  
    443   /** 
    444    * Checks the value of a cookie. 
    445    * 
    446    * @param string $name   The cookie name 
    447    * @param mixed  $value  The expected value 
    448    * 
    449    * @return sfTestBrowser The current sfTestBrowser instance 
    450    */ 
    451   public function isCookie($name, $value) 
    452   { 
    453     if (!array_key_exists($name, $_COOKIE)) 
    454     { 
    455       $this->test()->fail(sprintf('cookie "%s" does not exist.', $name)); 
    456  
    457       return $this; 
    458     } 
    459  
    460     if (preg_match('/^(!)?([^a-zA-Z0-9\\\\]).+?\\2[ims]?$/', $value, $match)) 
    461     { 
    462       if ($match[1] == '!') 
    463       { 
    464         $this->test()->unlike($_COOKIE[$name], substr($value, 1), sprintf('cookie "%s" content does not match regex "%s"', $name, $value)); 
    465       } 
    466       else 
    467       { 
    468         $this->test()->like($_COOKIE[$name], $value, sprintf('cookie "%s" content matches regex "%s"', $name, $value)); 
    469       } 
    470     } 
    471     else if (null !== $message) 
    472     { 
    473       $this->test()->is($_COOKIE[$name], $value, sprintf('cookie "%s" content is ok', $name)); 
    474     } 
    475  
    476     return $this; 
    477   } 
    478  
    479   /** 
    480    * Tests if the given uri is cached. 
    481    * 
    482    * @param  boolean $boolean      Flag for checking the cache 
    483    * @param  boolean $with_layout  If have or not layout 
    484    * 
    485    * @return sfTestBrowser The current sfTestBrowser instance 
    486    */ 
    487   public function isCached($boolean, $with_layout = false) 
    488   { 
    489     return $this->isUriCached($this->context->getRouting()->getCurrentInternalUri(), $boolean, $with_layout); 
    490   } 
    491  
    492   /** 
    493    * Tests if the given uri is cached. 
    494    * 
    495    * @param  string  $uri          Uniform resource identifier 
    496    * @param  boolean $boolean      Flag for checking the cache 
    497    * @param  boolean $with_layout  If have or not layout 
    498    * 
    499    * @return sfTestBrowser The current sfTestBrowser instance 
    500    */ 
    501   public function isUriCached($uri, $boolean, $with_layout = false) 
    502   { 
    503     $cacheManager = $this->context->getViewCacheManager(); 
    504  
    505     // check that cache is enabled 
    506     if (!$cacheManager) 
    507     { 
    508       $this->test()->ok(!$boolean, 'cache is disabled'); 
    509  
    510       return $this; 
    511     } 
    512  
    513     if ($uri == $this->context->getRouting()->getCurrentInternalUri()) 
    514     { 
    515       $main = true; 
    516       $type = $with_layout ? 'page' : 'action'; 
    517     } 
    518     else 
    519     { 
    520       $main = false; 
    521       $type = $uri; 
    522     } 
    523  
    524     // check layout configuration 
    525     if ($cacheManager->withLayout($uri) && !$with_layout) 
    526     { 
    527       $this->test()->fail('cache without layout'); 
    528       $this->test()->skip('cache is not configured properly', 2); 
    529     } 
    530     else if (!$cacheManager->withLayout($uri) && $with_layout) 
    531     { 
    532       $this->test()->fail('cache with layout'); 
    533       $this->test()->skip('cache is not configured properly', 2); 
    534     } 
    535     else 
    536     { 
    537       $this->test()->pass('cache is configured properly'); 
    538  
    539       // check page is cached 
    540       $ret = $this->test()->is($cacheManager->has($uri), $boolean, sprintf('"%s" %s in cache', $type, $boolean ? 'is' : 'is not')); 
    541  
    542       // check that the content is ok in cache 
    543       if ($boolean) 
    544       { 
    545         if (!$ret) 
    546         { 
    547           $this->test()->fail('content in cache is ok'); 
    548         } 
    549         else if ($with_layout) 
    550         { 
    551           $response = unserialize($cacheManager->get($uri)); 
    552           $content = $response->getContent(); 
    553           $this->test()->ok($content == $this->getResponse()->getContent(), 'content in cache is ok'); 
    554         } 
    555         else 
    556         { 
    557           $ret = unserialize($cacheManager->get($uri)); 
    558           $content = $ret['content']; 
    559           $this->test()->ok(false !== strpos($this->getResponse()->getContent(), $content), 'content in cache is ok'); 
    560         } 
    561       } 
    562     } 
    563  
    564     return $this; 
    56551  } 
    56652} 
    567  
    568 if (!defined('E_RECOVERABLE_ERROR')) 
    569 { 
    570   define('E_RECOVERABLE_ERROR', 4096); 
    571 } 
    572  
    573 /** 
    574  * Error handler for the current test browser instance. 
    575  * 
    576  * @param mixed  $errno    Error number 
    577  * @param string $errstr   Error message 
    578  * @param string $errfile  Error file 
    579  * @param mixed  $errline  Error line 
    580  */ 
    581 function sfTestBrowserErrorHandler($errno, $errstr, $errfile, $errline) 
    582 { 
    583   if (($errno & error_reporting()) == 0) 
    584   { 
    585     return; 
    586   } 
    587  
    588   $msg = sprintf('PHP send a "%%s" error at %s line %s (%s)', $errfile, $errline, $errstr); 
    589   switch ($errno) 
    590   { 
    591     case E_WARNING: 
    592       throw new Exception(sprintf($msg, 'warning')); 
    593       break; 
    594     case E_NOTICE: 
    595       throw new Exception(sprintf($msg, 'notice')); 
    596       break; 
    597     case E_STRICT: 
    598       throw new Exception(sprintf($msg, 'strict')); 
    599       break; 
    600     case E_RECOVERABLE_ERROR: 
    601       throw new Exception(sprintf($msg, 'catchable')); 
    602       break; 
    603   } 
    604 } 
    605  
    606 set_error_handler('sfTestBrowserErrorHandler'); 
  • branches/1.2/lib/util/sfBrowser.class.php

    r11020 r11116  
    33/* 
    44 * This file is part of the symfony package. 
    5  * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com> 
     5 * (c) Fabien Potencier <fabien.potencier@symfony-project.com> 
    66 * 
    77 * For the full copyright and license information, please view the LICENSE 
     
    1010 
    1111/** 
    12  * sfBrowser simulates a fake browser which can surf a symfony application. 
     12 * sfBrowser simulates a browser which can surf a symfony application. 
    1313 * 
    1414 * @package    symfony 
     
    1717 * @version    SVN: $Id$ 
    1818 */ 
    19 class sfBrowser 
     19class sfBrowser extends sfBrowserBase 
    2020{ 
    2121  protected 
    22     $context            = null, 
    23     $hostname           = null, 
    24     $remote             = null, 
    25     $dom                = null, 
    26     $stack              = array(), 
    27     $stackPosition      = -1, 
    28     $cookieJar          = array(), 
    29     $fields             = array(), 
    30     $files              = array(), 
    31     $vars               = array(), 
    32     $defaultServerArray = array(), 
    33     $headers            = array(), 
    34     $currentException   = null; 
    35  
    36   /** 
    37    * Class constructor. 
    38    * 
    39    * @param string $hostname  Hostname to browse 
    40    * @param string $remote    Remote address to spook 
    41    * @param array  $options   Options for sfBrowser 
    42    * 
    43    * @return void 
    44    */ 
    45   public function __construct($hostname = null, $remote = null, $options = array()) 
    46   { 
    47     $this->initialize($hostname, $remote, $options); 
    48   } 
    49  
    50   /** 
    51    * Initializes sfBrowser - sets up environment 
    52    * 
    53    * @param string $hostname  Hostname to browse 
    54    * @param string $remote    Remote address to spook 
    55    * @param array  $options   Options for sfBrowser 
    56    * 
    57    * @return void 
    58    */ 
    59   public function initialize($hostname = null, $remote = null, $options = array()) 
    60   { 
    61     unset($_SERVER['argv']); 
    62     unset($_SERVER['argc']); 
    63  
    64     // setup our fake environment 
    65     $this->hostname = $hostname; 
    66     $this->remote   = $remote; 
    67  
    68     sfConfig::set('sf_test', true); 
    69  
    70     // we set a session id (fake cookie / persistence) 
    71     $this->newSession(); 
    72  
    73     // store default global $_SERVER array 
    74     $this->defaultServerArray = $_SERVER; 
    75  
    76     // register our shutdown function 
    77     register_shutdown_function(array($this, 'shutdown')); 
    78   } 
    79  
    80   /** 
    81    * Sets variable name 
    82    * 
    83    * @param string $name   The variable name 
    84    * @param mixed  $value  The value 
    85    * 
    86    * @return sfBrowser 
    87    */ 
    88   public function setVar($name, $value) 
    89   { 
    90     $this->vars[$name] = $value; 
    91  
    92     return $this; 
    93   } 
    94  
    95   /** 
    96    * Sets a HTTP header for the very next request. 
    97    * 
    98    * @param string $header  The header name 
    99    * @param string $value   The header value 
    100    */ 
    101   public function setHttpHeader($header, $value) 
    102   { 
    103     $this->headers[$header] = $value; 
    104  
    105     return $this; 
    106   } 
    107  
    108   /** 
    109    * Sets a cookie. 
    110    * 
    111    * @param  string  $name     The cookie name 
    112    * @param  string  $name     HTTP header name 
    113    * @param  string  $value    Value for the cookie 
    114    * @param  string  $expire   Cookie expiration period 
    115    * @param  string  $path     Path 
    116    * @param  string  $domain   Domain name 
    117    * @param  bool    $secure   If secure 
    118    * @param  bool    $httpOnly If uses only HTTP 
    119    *  
    120    * @return sfBrowser         This sfBrowser instance 
    121    */ 
    122   public function setCookie($name, $value, $expire = null, $path = '/', $domain = '', $secure = false, $httpOnly = false) 
    123   { 
    124     $this->cookieJar[$name] = array( 
    125       'name'     => $name, 
    126       'value'    => $value, 
    127       'expire'   => $expire, 
    128       'path'     => $path, 
    129       'domain'   => $domain, 
    130       'secure'   => (Boolean) $secure, 
    131       'httpOnly' => $httpOnly, 
    132     ); 
    133  
    134     return $this; 
    135   } 
    136  
    137   /** 
    138    * Removes a cookie by name. 
    139    * 
    140    * @param string $name The cookie name 
    141    * 
    142    * @return sfBrowser    This sfBrowser instance 
    143    */ 
    144   public function removeCookie($name) 
    145   { 
    146     unset($this->cookieJar[$name]); 
    147  
    148     return $this; 
    149   } 
    150  
    151   /** 
    152    * Clears all cookies. 
    153    * 
    154    * @return sfBrowser    This sfBrowser instance 
    155    */ 
    156   public function clearCookies() 
    157   { 
    158     $this->cookieJar = array(); 
    159  
    160     return $this; 
    161   } 
    162  
    163   /** 
    164    * Sets username and password for simulating http authentication. 
    165    * 
    166    * @param string $username  The username 
    167    * @param string $password  The password 
    168    * 
    169    * @return sfBrowser 
    170    */ 
    171   public function setAuth($username, $password) 
    172   { 
    173     $this->vars['PHP_AUTH_USER'] = $username; 
    174     $this->vars['PHP_AUTH_PW']   = $password; 
    175  
    176     return $this; 
    177   } 
    178  
    179   /** 
    180    * Gets a uri. 
    181    * 
    182    * @param string $uri         The URI to fetch 
    183    * @param array  $parameters  The Request parameters 
    184    * 
    185    * @return sfBrowser 
    186    */ 
    187   public function get($uri, $parameters = array()) 
    188   { 
    189     return $this->call($uri, 'get', $parameters); 
    190   } 
    191  
    192   /** 
    193    * Posts a uri. 
    194    * 
    195    * @param string $uri         The URI to fetch 
    196    * @param array  $parameters  The Request parameters 
    197    * 
    198    * @return sfBrowser 
    199    */ 
    200   public function post($uri, $parameters = array()) 
    201   { 
    202     return $this->call($uri, 'post', $parameters); 
    203   } 
     22    $context = null; 
    20423 
    20524  /** 
    20625   * Calls a request to a uri. 
    207    * 
    208    * @param string $uri          The URI to fetch 
    209    * @param string $method       The request method 
    210    * @param array  $parameters   The Request parameters 
    211    * @param bool   $changeStack  Change the browser history stack? 
    212    * 
    213    * @return sfBrowser 
    21426   */ 
    215   public function call($uri, $method = 'get', $parameters = array(), $changeStack = true
     27  protected function doCall(
    21628  { 
    217     // check that the previous call() hasn't returned an uncatched exception 
    218     $this->checkCurrentExceptionIsEmpty(); 
    219  
    220     $uri = $this->fixUri($uri); 
    221  
    222     // add uri to the stack 
    223     if ($changeStack) 
    224     { 
    225       $this->stack = array_slice($this->stack, 0, $this->stackPosition + 1); 
    226       $this->stack[] = array( 
    227         'uri'        => $uri, 
    228         'method'     => $method, 
    229         'parameters' => $parameters, 
    230       ); 
    231       $this->stackPosition = count($this->stack) - 1; 
    232     } 
    233  
    234     list($path, $query_string) = false !== ($pos = strpos($uri, '?')) ? array(substr($uri, 0, $pos), substr($uri, $pos + 1)) : array($uri, ''); 
    235     $query_string = html_entity_decode($query_string); 
    236  
    237     // remove anchor 
    238     $path = preg_replace('/#.*/', '', $path); 
    239  
    240     // removes all fields from previous request 
    241     $this->fields = array(); 
    242  
    243     // prepare the request object 
    244     $_SERVER = $this->defaultServerArray; 
    245     $_SERVER['HTTP_HOST']       = $this->hostname ? $this->hostname : sfConfig::get('sf_app').'-'.sfConfig::get('sf_environment'); 
    246     $_SERVER['SERVER_NAME']     = $_SERVER['HTTP_HOST']; 
    247     $_SERVER['SERVER_PORT']     = 80; 
    248     $_SERVER['HTTP_USER_AGENT'] = 'PHP5/CLI'; 
    249     $_SERVER['REMOTE_ADDR']     = $this->remote ? $this->remote : '127.0.0.1'; 
    250     $_SERVER['REQUEST_METHOD']  = strtoupper($method); 
    251     $_SERVER['PATH_INFO']       = $path; 
    252     $_SERVER['REQUEST_URI']     = '/index.php'.$uri; 
    253     $_SERVER['SCRIPT_NAME']     = '/index.php'; 
    254     $_SERVER['SCRIPT_FILENAME'] = '/index.php'; 
    255     $_SERVER['QUERY_STRING']    = $query_string; 
    256     foreach ($this->vars as $key => $value) 
    257     { 
    258       $_SERVER[strtoupper($key)] = $value; 
    259     } 
    260  
    261     foreach ($this->headers as $header => $value) 
    262     { 
    263       $_SERVER['HTTP_'.strtoupper(str_replace('-', '_', $header))] = $value; 
    264     } 
    265     $this->headers = array(); 
    266  
    267     // request parameters 
    268     $_GET = $_POST = array(); 
    269     if (strtoupper($method) == 'POST') 
    270     { 
    271       $_POST = $parameters; 
    272     } 
    273     if (strtoupper($method) == 'GET') 
    274     { 
    275       $_GET  = $parameters; 
    276     } 
    277  
    278     // handle input type="file" fields 
    279     if (count($this->files)) 
    280     { 
    281       $_FILES = $this->files; 
    282     } 
    283     $this->files = array(); 
    284  
    285     parse_str($query_string, $qs); 
    286     if (is_array($qs)) 
    287     { 
    288       $_GET = array_merge($qs, $_GET); 
    289     } 
    290  
    291     // expire cookies 
    292     $cookies = $this->cookieJar; 
    293     foreach ($cookies as $name => $cookie) 
    294     { 
    295       if ($cookie['expire'] && $cookie['expire'] < time()) 
    296       { 
    297         unset($this->cookieJar[$name]); 
    298       } 
    299     } 
    300  
    301     // restore cookies 
    302     $_COOKIE = array(); 
    303     foreach ($this->cookieJar as $name => $cookie) 
    304     { 
    305       $_COOKIE[$name] = $cookie['value']; 
    306     } 
    307  
    308     ob_start(); 
    309  
    31029    // recycle our context object 
    31130    $this->context = $this->getContext(true); 
    31231 
    313     // launch request via controller 
    314     $controller = $this->context->getController(); 
    315     $request    = $this->context->getRequest(); 
    316     $response   = $this->context->getResponse(); 
     32    sfConfig::set('sf_test', true); 
    31733 
    31834    // we register a fake rendering filter 
    31935    sfConfig::set('sf_rendering_filter', array('sfFakeRenderingFilter', null)); 
    32036 
    321     $this->currentException = null
     37    $this->resetCurrentException()
    32238 
    32339    // dispatch our request 
    324     $controller->dispatch(); 
    325  
     40    ob_start(); 
     41    $this->context->getController()->dispatch(); 
    32642    $retval = ob_get_clean(); 
    32743 
    32844    // append retval to the response content 
    329     $response->setContent($retval); 
     45    $this->context->getResponse()->setContent($retval); 
    33046 
    33147    // manually shutdown user to save current session data 
    33248    $this->context->getUser()->shutdown(); 
    33349    $this->context->getStorage()->shutdown(); 
    334  
    335     // save cookies 
    336     foreach ($response->getCookies() as $name => $cookie) 
    337     { 
    338       // FIXME: deal with path, secure, ... 
    339       $this->cookieJar[$name] = $cookie; 
    340     } 
    341  
    342     // support for the ETag header 
    343     if ($etag = $this->context->getResponse()->getHttpHeader('Etag')) 
    344     { 
    345       $this->vars['HTTP_IF_NONE_MATCH'] = $etag; 
    346     } 
    347     else 
    348     { 
    349       unset($this->vars['HTTP_IF_NONE_MATCH']); 
    350     } 
    351  
    352     // support for the last modified header 
    353     if ($lastModified = $this->context->getResponse()->getHttpHeader('Last-Modified')) 
    354     { 
    355       $this->vars['HTTP_IF_MODIFIED_SINCE'] = $lastModified; 
    356     } 
    357     else 
    358     { 
    359       unset($this->vars['HTTP_IF_MODIFIED_SINCE']); 
    360     } 
    361  
    362     // for HTML/XML content, create a DOM and sfDomCssSelector objects for the response content 
    363     if (preg_match('/(x|ht)ml/i', $response->getContentType(), $matches)) 
    364     { 
    365       $this->dom = new DomDocument('1.0', sfConfig::get('sf_charset')); 
    366       $this->dom->validateOnParse = true; 
    367       if ('x' == $matches[1]) 
    368       { 
    369         @$this->dom->loadXML($response->getContent()); 
    370       } 
    371       else 
    372       { 
    373         @$this->dom->loadHTML($response->getContent()); 
    374       } 
    375       $this->domCssSelector = new sfDomCssSelector($this->dom); 
    376     } 
    377     else 
    378     { 
    379       $this->dom = null; 
    380       $this->domCssSelector = null; 
    381     } 
    382  
    383     return $this; 
    384   } 
    385  
    386   /** 
    387    * Go back in the browser history stack. 
    388    * 
    389    * @return sfBrowser 
    390    */ 
    391   public function back() 
    392   { 
    393     if ($this->stackPosition < 1) 
    394     { 
    395       throw new sfException('You are already on the first page.'); 
    396     } 
    397  
    398     --$this->stackPosition; 
    399     return $this->call($this->stack[$this->stackPosition]['uri'], $this->stack[$this->stackPosition]['method'], $this->stack[$this->stackPosition]['parameters'], false); 
    400   } 
    401  
    402   /** 
    403    * Go forward in the browser history stack. 
    404    * 
    405    * @return sfBrowser 
    406    */ 
    407   public function forward() 
    408   { 
    409     if ($this->stackPosition > count($this->stack) - 2) 
    410     { 
    411       throw new sfException('You are already on the last page.'); 
    412     } 
    413  
    414     ++$this->stackPosition; 
    415     return $this->call($this->stack[$this->stackPosition]['uri'], $this->stack[$this->stackPosition]['method'], $this->stack[$this->stackPosition]['parameters'], false); 
    416   } 
    417  
    418   /** 
    419    * Reload the current browser. 
    420    * 
    421    * @return sfBrowser 
    422    */ 
    423   public function reload() 
    424   { 
    425     if (-1 == $this->stackPosition) 
    426     { 
    427       throw new sfException('No page to reload.'); 
    428     } 
    429  
    430     return $this->call($this->stack[$this->stackPosition]['uri'], $this->stack[$this->stackPosition]['method'], $this->stack[$this->stackPosition]['parameters'], false); 
    431   } 
    432  
    433   /** 
    434    * Get response dom css selector. 
    435    * 
    436    * @return sfDomCssSelector 
    437    */ 
    438   public function getResponseDomCssSelector() 
    439   { 
    440     if (is_null($this->dom)) 
    441     { 
    442       throw new sfException('The DOM is not accessible because the browser response content type is not HTML.'); 
    443     } 
    444  
    445     return $this->domCssSelector; 
    446   } 
    447  
    448   /** 
    449    * Get response dom. 
    450    * 
    451    * @return sfDomCssSelector 
    452    */ 
    453   public function getResponseDom() 
    454   { 
    455     if (is_null($this->dom)) 
    456     { 
    457       throw new sfException('The DOM is not accessible because the browser response content type is not HTML.'); 
    458     } 
    459  
    460     return $this->dom; 
    46150  } 
    46251 
     
    512101 
    513102  /** 
    514    * Gets current exception
     103   * Gets user
    515104   * 
    516    * @return sfException 
     105   * @return sfUser 
    517106   */ 
    518   public function getCurrentException() 
     107  public function getUser() 
    519108  { 
    520     return $this->currentException; 
    521   } 
    522  
    523   /** 
    524    * Resets the current exception. 
    525    */ 
    526   public function resetCurrentException() 
    527   { 
    528     $this->currentException = null; 
    529   } 
    530  
    531   /** 
    532    * Test for an uncaught exception. 
    533    * 
    534    * @return  boolean 
    535    */ 
    536   public function checkCurrentExceptionIsEmpty() 
    537   { 
    538     return is_null($this->getCurrentException()) || $this->getCurrentException() instanceof sfError404Exception; 
    539   } 
    540  
    541   /** 
    542    * Follow redirects? 
    543    * 
    544    * @throws sfException If request was not a redirect 
    545    * 
    546    * @return sfBrowser 
    547    */ 
    548   public function followRedirect() 
    549   { 
    550     if (null === $this->context->getResponse()->getHttpHeader('Location')) 
    551     { 
    552       throw new sfException('The request was not redirected.'); 
    553     } 
    554  
    555     return $this->get($this->context->getResponse()->getHttpHeader('Location')); 
    556   } 
    557  
    558   /** 
    559    * Sets a form field in the browser. 
    560    * 
    561    * @param string $name   The field name 
    562    * @param string $value  The field value 
    563    * 
    564    * @return sfBrowser 
    565    */ 
    566   public function setField($name, $value) 
    567   { 
    568     // as we don't know yet the form, just store name/value pairs 
    569     $this->parseArgumentAsArray($name, $value, $this->fields); 
    570  
    571     return $this; 
    572   } 
    573  
    574   /** 
    575    * Simulates a click on a link or button. 
    576    * 
    577    * @param string  $name       The link or button text 
    578    * @param array   $arguments  The arguments to pass to the link 
    579    * @param integer $position   The position of the linked to link if several ones have the same name 
    580    * 
    581    * @return sfBrowser 
    582    */ 
    583   public function click($name, $arguments = array(), $position = 0) 
    584   { 
    585     $dom = $this->getResponseDom(); 
    586  
    587     if (!$dom) 
    588     { 
    589       throw new sfException('Cannot click because there is no current page in the browser.'); 
    590     } 
    591  
    592     $xpath = new DomXpath($dom); 
    593  
    594     // text link 
    595     if ($link = $xpath->query(sprintf('//a[.="%s"]', $name))->item($position)) 
    596     { 
    597       return $this->get($link->getAttribute('href')); 
    598     } 
    599  
    600     // image link 
    601     if ($link = $xpath->query(sprintf('//a/img[@alt="%s"]/ancestor::a', $name))->item($position)) 
    602     { 
    603       return $this->get($link->getAttribute('href')); 
    604     } 
    605  
    606     // form 
    607     if (!$form = $xpath->query(sprintf('//input[((@type="submit" or @type="button") and @value="%s") or (@type="image" and @alt="%s")]/ancestor::form', $name, $name))->item($position)) 
    608     { 
    609       if (!$form = $xpath->query(sprintf('//button[.="%s" or @id="%s" or @name="%s"]/ancestor::form', $name, $name, $name))->item($position)) 
    610       { 
    611         throw new sfException(sprintf('Cannot find the "%s" link or button.', $name)); 
    612       } 
    613     } 
    614  
    615     // form attributes 
    616     $url = $form->getAttribute('action'); 
    617     $method = $form->getAttribute('method') ? strtolower($form->getAttribute('method')) : 'get'; 
    618  
    619     // merge form default values and arguments 
    620     $defaults = array(); 
    621     $arguments = sfToolkit::arrayDeepMerge($this->fields, $arguments); 
    622  
    623     foreach ($xpath->query('descendant::input | descendant::textarea | descendant::select', $form) as $element) 
    624     { 
    625       $elementName = $element->getAttribute('name'); 
    626       $nodeName    = $element->nodeName; 
    627       $value       = null; 
    628  
    629       if ($nodeName == 'input' && ($element->getAttribute('type') == 'checkbox' || $element->getAttribute('type') == 'radio')) 
    630       { 
    631         if ($element->getAttribute('checked')) 
    632         { 
    633           $value = $element->hasAttribute('value') ? $element->getAttribute('value') : '1'; 
    634         } 
    635       } 
    636       else if ($nodeName == 'input' && $element->getAttribute('type') == 'file') 
    637       { 
    638         $ph = new sfParameterHolder(); 
    639         $ph->add($arguments); 
    640  
    641         $filename = $ph->get($elementName, ''); 
    642  
    643         if (is_readable($filename)) 
    644         { 
    645           $fileError = UPLOAD_ERR_OK; 
    646           $fileSize = filesize($filename); 
    647         } 
    648         else 
    649         { 
    650           $fileError = UPLOAD_ERR_NO_FILE; 
    651           $fileSize = 0; 
    652         } 
    653  
    654         $ph->remove($elementName); 
    655         $arguments = $ph->getAll(); 
    656  
    657         $this->parseArgumentAsArray($elementName, array('name' => basename($filename), 'type' => '', 'tmp_name' => $filename, 'error' => $fileError, 'size' => $fileSize), $this->files); 
    658       } 
    659       else if ( 
    660         $nodeName == 'input' 
    661         && 
    662         (($element->getAttribute('type') != 'submit' && $element->getAttribute('type') != 'button') || $element->getAttribute('value') == $name) 
    663         && 
    664         ($element->getAttribute('type') != 'image' || $element->getAttribute('alt') == $name) 
    665       ) 
    666       { 
    667         $value = $element->getAttribute('value'); 
    668       } 
    669       else if ($nodeName == 'textarea') 
    670       { 
    671         $value = ''; 
    672         foreach ($element->childNodes as $el) 
    673         { 
    674           $value .= $dom->saveXML($el); 
    675         } 
    676       } 
    677       else if ($nodeName == 'select') 
    678       { 
    679         if ($multiple = $element->hasAttribute('multiple')) 
    680         { 
    681           $elementName = str_replace('[]', '', $elementName); 
    682           $value = array(); 
    683         } 
    684         else 
    685         { 
    686           $value = null; 
    687         } 
    688  
    689         $found = false; 
    690         foreach ($xpath->query('descendant::option', $element) as $option) 
    691         { 
    692           if ($option->getAttribute('selected')) 
    693           { 
    694             $found = true; 
    695             if ($multiple) 
    696             { 
    697               $value[] = $option->getAttribute('value'); 
    698             } 
    699             else 
    700             { 
    701               $value = $option->getAttribute('value'); 
    702             } 
    703           } 
    704         } 
    705  
    706         // if no option is selected and if it is a simple select box, take the first option as the value 
    707         $option = $xpath->query('descendant::option', $element)->item(0); 
    708         if (!$found && !$multiple && $option instanceof DOMElement) 
    709         { 
    710           $value = $option->getAttribute('value'); 
    711         } 
    712       } 
    713  
    714       if (null !== $value) 
    715       { 
    716         $this->parseArgumentAsArray($elementName, $value, $defaults); 
    717       } 
    718     } 
    719  
    720     // create request parameters 
    721     $arguments = sfToolkit::arrayDeepMerge($defaults, $arguments); 
    722     if ('post' == $method) 
    723     { 
    724       return $this->post($url, $arguments); 
    725     } 
    726     else 
    727     { 
    728       $query_string = http_build_query($arguments, null, '&'); 
    729       $sep = false === strpos($url, '?') ? '?' : '&'; 
    730  
    731       return $this->get($url.($query_string ? $sep.$query_string : '')); 
    732     } 
    733   } 
    734  
    735   /** 
    736    * Parses arguments as array 
    737    * 
    738    * @param string $name   The argument name 
    739    * @param string $value  The argument value 
    740    * @param array  $vars 
    741    */ 
    742   protected function parseArgumentAsArray($name, $value, &$vars) 
    743   { 
    744     if (false !== $pos = strpos($name, '[')) 
    745     { 
    746       $var = &$vars; 
    747       $tmps = array_filter(preg_split('/(\[ | \[\] | \])/x', $name), create_function('$s', 'return $s !== "";')); 
    748       foreach ($tmps as $tmp) 
    749       { 
    750         $var = &$var[$tmp]; 
    751       } 
    752       if ($var) 
    753       { 
    754         if (!is_array($var)) 
    755         { 
    756           $var = array($var); 
    757         } 
    758         $var[] = $value; 
    759       } 
    760       else 
    761       { 
    762         $var = $value; 
    763       } 
    764     } 
    765     else 
    766     { 
    767       $vars[$name] = $value; 
    768     } 
    769   } 
    770  
    771   /** 
    772    * Reset browser to original state 
    773    * 
    774    * @return sfBrowser 
    775    */ 
    776   public function restart() 
    777   { 
    778     $this->newSession(); 
    779     $this->cookieJar     = array(); 
    780     $this->stack         = array(); 
    781     $this->fields        = array(); 
    782     $this->vars          = array(); 
    783     $this->dom           = null; 
    784     $this->stackPosition = -1; 
    785  
    786     return $this; 
     109    return $this->context->getUser(); 
    787110  } 
    788111 
     
    794117  public function shutdown() 
    795118  { 
    796     $this->checkCurrentExceptionIsEmpty(); 
     119    parent::shutdown(); 
    797120 
    798121    // we remove all session data 
    799122    sfToolkit::clearDirectory(sfConfig::get('sf_test_cache_dir').'/sessions'); 
    800   } 
    801  
    802   /** 
    803    * Fixes uri removing # declarations and front controller. 
    804    * 
    805    * @param  string $uri  The URI to fix 
    806    * @return string The fixed uri 
    807    */ 
    808   protected function fixUri($uri) 
    809   { 
    810     // remove absolute information if needed (to be able to do follow redirects, click on links, ...) 
    811     if (0 === strpos($uri, 'http')) 
    812     { 
    813       // detect secure request 
    814       if (0 === strpos($uri, 'https')) 
    815       { 
    816         $this->defaultServerArray['HTTPS'] = 'on'; 
    817       } 
    818       else 
    819       { 
    820         unset($this->defaultServerArray['HTTPS']); 
    821       } 
    822  
    823       $uri = substr($uri, strpos($uri, 'index.php') + strlen('index.php')); 
    824     } 
    825     $uri = str_replace('/index.php', '', $uri); 
    826  
    827     // # as a uri 
    828     if ($uri && '#' == $uri[0]) 
    829     { 
    830       $uri = $this->stack[$this->stackPosition]['uri'].$uri; 
    831     } 
    832  
    833     return $uri; 
    834   } 
    835  
    836   /** 
    837    * Creates a new session in the browser. 
    838    * 
    839    * @return void 
    840    */ 
    841   protected function newSession() 
    842   { 
    843     $this->defaultServerArray['session_id'] = $_SERVER['session_id'] = md5(uniqid(rand(), true)); 
    844123  } 
    845124 
     
    853132  public function listenToException(sfEvent $event) 
    854133  { 
    855     $this->currentException = $event->getSubject(); 
     134    $this->setCurrentException($event->getSubject()); 
    856135  } 
    857136} 
  • branches/1.2/test/functional/sfTestBrowserTest.php

    r10830 r11116  
    7676  $b->test()->fail('The DOM is not accessible if the response content type is not HTML'); 
    7777} 
    78 catch (sfException $e) 
     78catch (LogicException $e) 
    7979{ 
    8080  $b->test()->pass('The DOM is not accessible if the response content type is not HTML'); 

The Sensio Labs Network

Since 1998, Sensio Labs has been promoting the Open-Source software movement by providing quality web application development, training, consulting, and supporting several large Open-Source projects.