Version: current

      1 <?php
      2 /**
      3  * Represents a test usage session of a web-app
      4  * It will maintain session-state from request to request
      5  *
      6  * @package sapphire
      7  * @subpackage testing
      8  */
      9 class TestSession {
     10     private $session;
     11     private $lastResponse;
     12
     13     /**
     14      * @param Controller $controller Necessary to use the mock session
     15      * created in {@link session} in the normal controller stack,
     16      * e.g. to overwrite Member::currentUser() with custom login data.
     17      */
     18     protected $controller;
     19
     20     /**
     21      * @var string $lastUrl Fake HTTP Referer Tracking, set in {@link get()} and {@link post()}.
     22      */
     23     private $lastUrl;
     24
     25     function __construct() {
     26         $this->session = new Session(array());
     27         $this->controller = new Controller();
     28         $this->controller->setSession($this->session);
     29         $this->controller->pushCurrent();
     30     }
     31
     32     function __destruct() {
     33         // Shift off anything else that's on the stack.  This can happen if something throws
     34         // an exception that causes a premature TestSession::__destruct() call
     35         while(Controller::curr() != $this->controller) Controller::curr()->popCurrent();
     36
     37         $this->controller->popCurrent();
     38     }
     39
     40     /**
     41      * Submit a get request
     42      * @uses Director::test()
     43      */
     44     function get($url, $session = null, $headers = null, $cookies = null) {
     45         $headers = (array) $headers;
     46         if($this->lastUrl) $headers['Referer'] = $this->lastUrl;
     47         $this->lastResponse = Director::test($url, null, $session ? $session : $this->session, null, null, $headers, $cookies);
     48         $this->lastUrl = $url;
     49         if(!$this->lastResponse) user_error("Director::test($url) returned null", E_USER_WARNING);
     50         return $this->lastResponse;
     51     }
     52
     53     /**
     54      * Submit a post request
     55      * @uses Director::test()
     56      */
     57     function post($url, $data, $headers = null, $session = null, $body = null, $cookies = null) {
     58         $headers = (array) $headers;
     59         if($this->lastUrl) $headers['Referer'] = $this->lastUrl;
     60         $this->lastResponse = Director::test($url, $data, $session ? $session : $this->session, null, $body, $headers, $cookies);
     61         $this->lastUrl = $url;
     62         if(!$this->lastResponse) user_error("Director::test($url) returned null", E_USER_WARNING);
     63         return $this->lastResponse;
     64     }
     65
     66     /**
     67      * Submit the form with the given HTML ID, filling it out with the given data.
     68      * Acts on the most recent response
     69      */
     70     function submitForm($formID, $button = null, $data = array()) {
     71         $page = $this->lastPage();
     72         if($page) {
     73             $form = $page->getFormById($formID);
     74
     75             foreach($data as $k => $v) {
     76                 $form->setField(new SimpleByName($k), $v);
     77             }
     78
     79             if($button) $submission = $form->submitButton(new SimpleByName($button));
     80             else $submission = $form->submit();
     81
     82             $url = Director::makeRelative($form->getAction()->asString());
     83
     84             $postVars = array();
     85             parse_str($submission->_encode(), $postVars);
     86             return $this->post($url, $postVars);
     87
     88         } else {
     89             user_error("TestSession::submitForm called when there is no form loaded.  Visit the page with the form first", E_USER_WARNING);
     90         }
     91     }
     92
     93     /**
     94      * If the last request was a 3xx response, then follow the redirection
     95      */
     96     function followRedirection() {
     97         if($this->lastResponse->getHeader('Location')) {
     98             $url = Director::makeRelative($this->lastResponse->getHeader('Location'));
     99             $url = strtok($url, '#');
    100             return $this->get($url);
    101         }
    102     }
    103
    104     /**
    105      * Returns true if the last response was a 3xx redirection
    106      */
    107     function wasRedirected() {
    108         $code = $this->lastResponse->getStatusCode();
    109         return $code >= 300 && $code < 400;
    110     }
    111
    112     /**
    113      * Get the most recent response, as an SS_HTTPResponse object
    114      */
    115     function lastResponse() {
    116         return $this->lastResponse;
    117     }
    118
    119     /**
    120      * Get the most recent response's content
    121      */
    122     function lastContent() {
    123         if(is_string($this->lastResponse)) return $this->lastResponse;
    124         else return $this->lastResponse->getBody();
    125     }
    126
    127     function cssParser() {
    128         return new CSSContentParser($this->lastContent());
    129     }
    130
    131
    132     /**
    133      * Get the last response as a SimplePage object
    134      */
    135     function lastPage() {
    136         require_once("thirdparty/simpletest/http.php");
    137         require_once("thirdparty/simpletest/page.php");
    138         require_once("thirdparty/simpletest/form.php");
    139
    140         $builder = new SimplePageBuilder();
    141         if($this->lastResponse) {
    142             $page = &$builder->parse(new TestSession_STResponseWrapper($this->lastResponse));
    143             $builder->free();
    144             unset($builder);
    145
    146             return $page;
    147         }
    148     }
    149
    150     /**
    151      * Get the current session, as a Session object
    152      */
    153     function session() {
    154         return $this->session;
    155     }
    156 }
    157
    158 /**
    159  * Wrapper around SS_HTTPResponse to make it look like a SimpleHTTPResposne
    160  *
    161  * @package sapphire
    162  * @subpackage testing
    163  */
    164 class TestSession_STResponseWrapper {
    165     private $response;
    166
    167     function __construct(SS_HTTPResponse $response) {
    168         $this->response = $response;
    169     }
    170
    171     function getContent() {
    172         return $this->response->getBody();
    173     }
    174
    175     function getError() {
    176         return "";
    177     }
    178
    179     function getSent() {
    180         return null;
    181     }
    182
    183     function getHeaders() {
    184         return "";
    185     }
    186
    187     function getMethod() {
    188         return "GET";
    189     }
    190
    191     function getUrl() {
    192         return "";
    193     }
    194
    195     function getRequestData() {
    196         return null;
    197     }
    198 }

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -