Permalink
Browse files

Update Slim_Http_Response with unit tests

  • Loading branch information...
1 parent c489fff commit c22aaf0400c95e64d1ebf321b3885f9147a04066 Josh Lockhart committed Dec 24, 2011
Showing with 708 additions and 325 deletions.
  1. +242 −91 Slim/Http/Response.php
  2. +466 −234 tests/Http/ResponseTest.php
View
333 Slim/Http/Response.php
@@ -2,11 +2,11 @@
/**
* Slim - a micro PHP 5 framework
*
- * @author Josh Lockhart <info@joshlockhart.com>
+ * @author Josh Lockhart <info@slimframework.com>
* @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com
* @license http://www.slimframework.com/license
- * @version 1.5.0
+ * @version 2.0.0
*
* MIT LICENSE
*
@@ -33,68 +33,189 @@
/**
* Response
*
- * Object-oriented representation of an HTTP response that is
- * returned to the client. This class is responsible for:
- *
- * - HTTP response status
- * - HTTP response body
- * - HTTP response headers
- * - HTTP response cookies
+ * This is a simple abstraction over top an HTTP response. This
+ * provides methods to set the HTTP status, the HTTP headers,
+ * and the HTTP body.
*
* @package Slim
- * @author Josh Lockhart <info@joshlockhart.com>
+ * @author Josh Lockhart
* @since Version 1.0
*/
-class Slim_Http_Response implements ArrayAccess, Iterator, Countable {
+class Slim_Http_Response implements ArrayAccess, Countable, IteratorAggregate {
/**
- * @var string HTTP response body
+ * @var int HTTP status code
*/
- protected $body;
+ protected $status;
/**
- * @var array HTTP response headers
+ * @var Slim_Http_Headers List of HTTP response headers
+ * @see Slim_Http_Headers
*/
protected $header;
/**
+ * @var string HTTP response body
+ */
+ protected $body;
+
+ /**
* @var int Length of HTTP response body
*/
protected $length;
/**
- * @var int HTTP status code
+ * @var array HTTP response codes and messages
*/
- protected $status;
+ protected static $messages = array(
+ //Informational 1xx
+ 100 => '100 Continue',
+ 101 => '101 Switching Protocols',
+ //Successful 2xx
+ 200 => '200 OK',
+ 201 => '201 Created',
+ 202 => '202 Accepted',
+ 203 => '203 Non-Authoritative Information',
+ 204 => '204 No Content',
+ 205 => '205 Reset Content',
+ 206 => '206 Partial Content',
+ //Redirection 3xx
+ 300 => '300 Multiple Choices',
+ 301 => '301 Moved Permanently',
+ 302 => '302 Found',
+ 303 => '303 See Other',
+ 304 => '304 Not Modified',
+ 305 => '305 Use Proxy',
+ 306 => '306 (Unused)',
+ 307 => '307 Temporary Redirect',
+ //Client Error 4xx
+ 400 => '400 Bad Request',
+ 401 => '401 Unauthorized',
+ 402 => '402 Payment Required',
+ 403 => '403 Forbidden',
+ 404 => '404 Not Found',
+ 405 => '405 Method Not Allowed',
+ 406 => '406 Not Acceptable',
+ 407 => '407 Proxy Authentication Required',
+ 408 => '408 Request Timeout',
+ 409 => '409 Conflict',
+ 410 => '410 Gone',
+ 411 => '411 Length Required',
+ 412 => '412 Precondition Failed',
+ 413 => '413 Request Entity Too Large',
+ 414 => '414 Request-URI Too Long',
+ 415 => '415 Unsupported Media Type',
+ 416 => '416 Requested Range Not Satisfiable',
+ 417 => '417 Expectation Failed',
+ 422 => '422 Unprocessable Entity',
+ 423 => '423 Locked',
+ //Server Error 5xx
+ 500 => '500 Internal Server Error',
+ 501 => '501 Not Implemented',
+ 502 => '502 Bad Gateway',
+ 503 => '503 Service Unavailable',
+ 504 => '504 Gateway Timeout',
+ 505 => '505 HTTP Version Not Supported'
+ );
/**
* Constructor
+ * @param string $body The HTTP response body
+ * @param int $status The HTTP response status
+ * @param array $header The HTTP response headers
*/
public function __construct( $body = '', $status = 200, $header = array() ) {
- $this->body = '';
- $this->header = array_merge(array('Content-Type' => 'text/html'), $header);
- $this->length = 0;
$this->status = (int)$status;
+ $this->header = new Slim_Http_Headers(array_merge(array('Content-Type' => 'text/html'), $header));
+ $this->body = '';
$this->write($body);
}
/**
- * Append the HTTP response body
- * @param string $body Content to append to the current HTTP response body
- * @return string The updated HTTP response body
+ * Get and set status
+ * @param int|null $status
+ * @return int
+ */
+ public function status( $status = null ) {
+ if ( !is_null($status) ) {
+ $this->status = (int)$status;
+ }
+ return $this->status;
+ }
+
+ /**
+ * Get and set header
+ * @param string $name Header name
+ * @param string|null $value Header value
+ * @return string Header value
*/
- public function write( $body ) {
- $this->body .= (string)$body;
+ public function header( $name, $value = null ) {
+ if ( !is_null($value) ) {
+ $this[$name] = $value;
+ }
+ return $this[$name];
+ }
+
+ /**
+ * Get headers
+ * @return Slim_Http_Headers
+ */
+ public function headers() {
+ return $this->header;
+ }
+
+ /**
+ * Get and set body
+ * @param string|null $body Content of HTTP response body
+ * @return string
+ */
+ public function body( $body = null ) {
+ if ( !is_null($body) ) {
+ $this->write($body, true);
+ }
+ return $this->body;
+ }
+
+ /**
+ * Get and set length
+ * @param int|null $length
+ * @return int
+ */
+ public function length( $length = null ) {
+ if ( !is_null($length) ) {
+ $this->length = (int)$length;
+ }
+ return $this->length;
+ }
+
+ /**
+ * Append HTTP response body
+ * @param string $body Content to append to the current HTTP response body
+ * @param bool $replace Overwrite existing response body?
+ * @return string The updated HTTP response body
+ */
+ public function write( $body, $replace = false ) {
+ if ( $replace ) {
+ $this->body = $body;
+ } else {
+ $this->body .= (string)$body;
+ }
$this->length = strlen($this->body);
- $this->header('Content-Length', $this->length);
+ $this['Content-Length'] = (string)$this->length;
return $this->body;
}
/**
* Finalize
+ *
+ * This prepares this response and returns an array
+ * of [status, headers, body]. This array is passed to outer middleware
+ * if available or directly to the Slim run method.
+ *
+ * @return array[int status, array headers, string body]
*/
public function finalize() {
if ( in_array($this->status, array(204, 304)) ) {
- unset($this->header['Content-Type'], $this->header['Content-Length']); //TODO: Abstract header array into own util class
+ unset($this['Content-Type'], $this['Content-Length']);
return array($this->status, $this->header, '');
} else {
return array($this->status, $this->header, $this->body);
@@ -103,37 +224,62 @@ public function finalize() {
/**
* Set cookie
+ *
+ * Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
+ * header on its own and delegates this responsibility to the `Slim_Http_Util` class. This
+ * response's header is passed by reference to the utility class and is directly modified. By not
+ * relying on PHP's native implementation, Slim allows middleware the opportunity to massage or
+ * analyze the raw header before the response is ultimately delivered to the HTTP client.
+ *
+ * @param string $name The name of the cookie
+ * @param string|array $value If string, the value of cookie; if array, properties for
+ * cookie including: value, expire, path, domain, secure, httponly
*/
- public function setCookie( $name, $valueOrArray ) {
- //Slim_Http_Util::setCookieHeader($this->header, $name, $valueOrArray);
+ public function setCookie( $name, $value ) {
+ Slim_Http_Util::setCookieHeader($this->header, $name, $value);
}
/**
* Delete cookie
+ *
+ * Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
+ * header on its own and delegates this responsibility to the `Slim_Http_Util` class. This
+ * response's header is passed by reference to the utility class and is directly modified. By not
+ * relying on PHP's native implementation, Slim allows middleware the opportunity to massage or
+ * analyze the raw header before the response is ultimately delivered to the HTTP client.
+ *
+ * This method will set a cookie with the given name that has an expiration time in the past; this will
+ * prompt the HTTP client to invalidate and remove the client-side cookie. Optionally, you may
+ * also pass a key/value array as the second argument. If the "domain" key is present in this
+ * array, only the Cookie with the given name AND domain will be removed. The invalidating cookie
+ * sent with this response will adopt all properties of the second argument.
+ *
+ * @param string $name The name of the cookie
+ * @param array $value Properties for cookie including: value, expire, path, domain, secure, httponly
*/
- public function deleteCookie( $name ) {
- //Slim_Http_Util::deleteCookieHeader($this->header, $name);
+ public function deleteCookie( $name, $value = array() ) {
+ Slim_Http_Util::deleteCookieHeader($this->header, $name, $value);
}
/**
- * Helpers: Empty?
+ * Redirect
+ *
+ * This method prepares this response to return an HTTP Redirect response
+ * to the HTTP client.
+ *
+ * @param string $url The redirect destination
+ * @param int $status The redirect HTTP status code
*/
- public function isEmpty() {
- return in_array($this->status, array(201, 204, 304));
+ public function redirect ( $url, $status = 302 ) {
+ $this->status = $status;
+ $this['Location'] = $url;
}
/**
- * Helpers: Client error?
- */
- public function isClientError() {
- return $this->status >= 400 && $this->status < 500;
- }
-
- /**
- * Helpers: Forbidden?
+ * Helpers: Empty?
*/
- public function isForbidden() {
- return $this->status === 403;
+ public function isEmpty() {
+ return in_array($this->status, array(201, 204, 304));
}
/**
@@ -144,17 +290,17 @@ public function isInformational() {
}
/**
- * Helpers: Not Found?
+ * Helpers: OK?
*/
- public function isNotFound() {
- return $this->status === 404;
+ public function isOk() {
+ return $this->status === 200;
}
/**
- * Helpers: OK?
+ * Helpers: Successful?
*/
- public function isOk() {
- return $this->status === 200;
+ public function isSuccessful() {
+ return $this->status >= 200 && $this->status < 300;
}
/**
@@ -165,91 +311,96 @@ public function isRedirect() {
}
/**
- * Helpers: Server Error?
+ * Helpers: Redirection?
*/
- public function isServerError() {
- return $this->status >= 500 && $this->status < 600;
+ public function isRedirection() {
+ return $this->status >= 300 && $this->status < 400;
}
/**
- * Helpers: Successful?
+ * Helpers: Forbidden?
*/
- public function isSuccessful() {
- return $this->status >= 200 && $this->status < 300;
+ public function isForbidden() {
+ return $this->status === 403;
}
/**
- * Array Access: Offset Exists
+ * Helpers: Not Found?
*/
- public function offsetExists( $offset ) {
- return isset($this->header[(string)$offset]);
+ public function isNotFound() {
+ return $this->status === 404;
}
/**
- * Array Access: Offset Get
+ * Helpers: Client error?
*/
- public function offsetGet( $offset ) {
- if ( isset($this->header[(string)$offset]) ) {
- return $this->header[(string)$offset];
- } else {
- return null;
- }
+ public function isClientError() {
+ return $this->status >= 400 && $this->status < 500;
}
/**
- * Array Access: Offset Set
+ * Helpers: Server Error?
*/
- public function offsetSet( $offset, $value ) {
- $this->header[(string)$offset] = (string)$value;
+ public function isServerError() {
+ return $this->status >= 500 && $this->status < 600;
}
/**
- * Array Access: Offset Unset
+ * Array Access: Offset Exists
*/
- public function offsetUnset( $offset ) {
- unset($this->header[(string)$offset]);
+ public function offsetExists( $offset ) {
+ return isset($this->header[$offset]);
}
/**
- * Iterable: Rewind
+ * Array Access: Offset Get
*/
- public function rewind() {
- reset($this->header);
+ public function offsetGet( $offset ) {
+ if ( isset($this->header[$offset]) ) {
+ return $this->header[$offset];
+ } else {
+ return null;
+ }
}
/**
- * Iterable: Current
+ * Array Access: Offset Set
*/
- public function current() {
- return current($this->header);
+ public function offsetSet( $offset, $value ) {
+ $this->header[$offset] = $value;
}
/**
- * Iterable: Key
+ * Array Access: Offset Unset
*/
- public function key() {
- return key($this->header);
+ public function offsetUnset( $offset ) {
+ unset($this->header[$offset]);
}
/**
- * Iterable: Next
+ * Countable: Count
*/
- public function next() {
- return next($this->header);
+ public function count() {
+ return count($this->header);
}
/**
- * Iterable: Valid
+ * IteratorAggregate
+ * @return ArrayIterator
*/
- public function valid() {
- return $this->current() !== false;
+ public function getIterator() {
+ return $this->header->getIterator();
}
/**
- * Countable: Count
+ * Get message for HTTP status code
+ * @return string|null
*/
- public function count() {
- return count($this->header);
+ public static function getMessageForCode( $status ) {
+ if ( isset(self::$messages[$status]) ) {
+ return self::$messages[$status];
+ } else {
+ return null;
+ }
}
-}
-?>
+}
View
700 tests/Http/ResponseTest.php
@@ -28,278 +28,510 @@
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
*/
-set_include_path(dirname(__FILE__) . '/../../' . PATH_SEPARATOR . get_include_path());
+set_include_path(dirname(__FILE__) . '/../' . PATH_SEPARATOR . get_include_path());
-require_once 'Slim/Http/CookieJar.php';
-require_once 'Slim/Http/Uri.php';
-require_once 'Slim/Http/Request.php';
+require_once 'Slim/Http/Headers.php';
+require_once 'Slim/Http/Util.php';
require_once 'Slim/Http/Response.php';
-class ResponseTest extends PHPUnit_Extensions_OutputTestCase {
-
- public function setUp() {
- $_SERVER['REDIRECT_STATUS'] = "200";
- $_SERVER['HTTP_HOST'] = "slim";
- $_SERVER['HTTP_CONNECTION'] = "keep-alive";
- $_SERVER['HTTP_CACHE_CONTROL'] = "max-age=0";
- $_SERVER['HTTP_ACCEPT'] = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
- $_SERVER['HTTP_USER_AGENT'] = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3";
- $_SERVER['HTTP_ACCEPT_ENCODING'] = "gzip,deflate,sdch";
- $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "en-US,en;q=0.8";
- $_SERVER['HTTP_ACCEPT_CHARSET'] = "ISO-8859-1,utf-8;q=0.7,*;q=0.3";
- $_SERVER['PATH'] = "/usr/bin:/bin:/usr/sbin:/sbin";
- $_SERVER['SERVER_SIGNATURE'] = "";
- $_SERVER['SERVER_SOFTWARE'] = "Apache";
- $_SERVER['SERVER_NAME'] = "slim";
- $_SERVER['SERVER_ADDR'] = "127.0.0.1";
- $_SERVER['SERVER_PORT'] = "80";
- $_SERVER['REMOTE_ADDR'] = "127.0.0.1";
- $_SERVER['DOCUMENT_ROOT'] = rtrim(dirname(__FILE__), '/');
- $_SERVER['SERVER_ADMIN'] = "you@example.com";
- $_SERVER['SCRIPT_FILENAME'] = __FILE__;
- $_SERVER['REMOTE_PORT'] = "55426";
- $_SERVER['REDIRECT_URL'] = "/";
- $_SERVER['GATEWAY_INTERFACE'] = "CGI/1.1";
- $_SERVER['SERVER_PROTOCOL'] = "HTTP/1.1";
- $_SERVER['REQUEST_METHOD'] = "GET";
- $_SERVER['QUERY_STRING'] = "";
- $_SERVER['REQUEST_URI'] = "/";
- $_SERVER['SCRIPT_NAME'] = basename(__FILE__);
- $_SERVER['PHP_SELF'] = '/'.basename(__FILE__);
- $_SERVER['REQUEST_TIME'] = "1285647051";
- $_SERVER['argv'] = array();
- $_SERVER['argc'] = 0;
- }
-
- /**
- * Test default response
- *
- * Pre-conditions:
- * None
- *
- * Post-conditions:
- * Response status is 200;
- * Headers array has "text/html" Content-Type
- * Cookies array is empty
- */
- public function testNewResponse() {
- $r = new Slim_Http_Response(new Slim_Http_Request());
+class ResponseTest extends PHPUnit_Framework_TestCase {
+ /**
+ * Test constructor without args
+ */
+ public function testConstructorWithoutArgs() {
+ $r = new Slim_Http_Response();
+ $this->assertEquals('', $r->body());
$this->assertEquals(200, $r->status());
- $this->assertEquals(array('Content-Type' => 'text/html'), $r->headers());
- }
-
- /**
- * Test status
- *
- * Pre-conditions:
- * Case A: Status code is a valid HTTP status code
- * Case B: Status code is not a valid HTTP status code
- *
- * Post-conditions:
- * Case A: The response status code is set and returned
- * Case B: An InvalidArgumentException is thrown
- */
- public function testResponseStatus() {
- //Case A
- $r1 = new Slim_Http_Response(new Slim_Http_Request());
- $newStatus = $r1->status(201);
- $this->assertEquals(201, $newStatus);
-
- //Case B
- $r2 = new Slim_Http_Response(new Slim_Http_Request());
- try {
- $r2->status(700);
- $this->fail('Did not throw exception when status code invalid');
- } catch ( InvalidArgumentException $e ) {}
- }
-
- /**
- * Test headers
- *
- * Pre-conditions:
- * Case A: Set Content-Type to 'application/json'
- * Case B: Get non-existent header
- *
- * Post-conditions:
- * Case A: Header is set correctly
- * Case B: Returned value is NULL
- */
- public function testResponseHeaders() {
- //Case A
- $r1 = new Slim_Http_Response(new Slim_Http_Request());
- $r1->header('Content-Type', 'application/json');
- $this->assertEquals('application/json', $r1->header('Content-Type'));
- $this->assertEquals(array('Content-Type' => 'application/json'), $r1->headers());
-
- //Case B
- $this->assertNull($r1->header('foo'));
- }
-
- /**
- * Test body and write
- *
- * Pre-conditions:
- * Case A: Response body set to "Foo bar"
- * Case B: Same response body is changed to "abc123"
- * Case C: Same response body is appended with "xyz"
- *
- * Post-conditions:
- * Case A: Response body is "Foo bar", and Content-Length = 7
- * Case B: Response body is "abc123" and Content-Length = 6
- * Case C: Response body is "abc123xyz" and Content-Length = 9
- */
- public function testBody() {
- //Case A
- $r1 = new Slim_Http_Response(new Slim_Http_Request());
- $r1->body('Foo bar');
- $this->assertEquals('Foo bar', $r1->body());
- $this->assertEquals(7, $r1->header('Content-Length'));
-
- //Case B
- $r1->body('abc123');
- $this->assertEquals('abc123', $r1->body());
- $this->assertEquals(6, $r1->header('Content-Length'));
-
- //Case C
- $r1->write('xyz');
- $this->assertEquals('abc123xyz', $r1->body());
- $this->assertEquals(9, $r1->header('Content-Length'));
+ $this->assertEquals(0, $r->length());
+ $this->assertEquals('text/html', $r['Content-Type']);
+ }
+
+ /**
+ * Test constructor with args
+ */
+ public function testConstructorWithArgs() {
+ $r = new Slim_Http_Response('Page Not Found', 404, array('Content-Type' => 'application/json', 'X-Created-By' => 'Slim'));
+ $this->assertEquals('Page Not Found', $r->body());
+ $this->assertEquals(404, $r->status());
+ $this->assertEquals(14, $r->length());
+ $this->assertEquals('application/json', $r['Content-Type']);
+ $this->assertEquals('Slim', $r['X-Created-By']);
+ }
+
+ /**
+ * Test get status
+ */
+ public function testGetStatus() {
+ $r = new Slim_Http_Response();
+ $this->assertEquals(200, $r->status());
+ }
+
+ /**
+ * Test set status
+ */
+ public function testSetStatus() {
+ $r = new Slim_Http_Response();
+ $r->status(500);
+ $this->assertEquals(500, $r->status());
+ }
+
+ /**
+ * Test get headers
+ */
+ public function testGetHeaders() {
+ $r = new Slim_Http_Response();
+ $headers = $r->headers();
+ $this->assertEquals(2, count($headers));
+ $this->assertEquals('text/html', $headers['Content-Type']);
+ }
+
+ /**
+ * Test get and set header (without Array Access)
+ */
+ public function testGetAndSetHeader() {
+ $r = new Slim_Http_Response();
+ $r->header('X-Foo', 'Bar');
+ $this->assertEquals('Bar', $r->header('X-Foo'));
+ }
+
+ /**
+ * Test get body
+ */
+ public function testGetBody() {
+ $r = new Slim_Http_Response('Foo');
+ $this->assertEquals('Foo', $r->body());
+ }
+
+ /**
+ * Test set body
+ */
+ public function testSetBody() {
+ $r = new Slim_Http_Response();
+ $r->body('Foo');
+ $this->assertEquals('Foo', $r->body());
+ }
+
+ /**
+ * Test get length
+ */
+ public function testGetLength() {
+ $r = new Slim_Http_Response('Foo');
+ $this->assertEquals(3, $r->length());
+ }
+
+ /**
+ * Test set length
+ */
+ public function testSetLength() {
+ $r = new Slim_Http_Response();
+ $r->length(3);
+ $this->assertEquals(3, $r->length());
+ }
+
+ /**
+ * Test write for appending
+ */
+ public function testWriteAppend() {
+ $r = new Slim_Http_Response('Foo');
+ $r->write('Bar');
+ $this->assertEquals('FooBar', $r->body());
+ }
+
+ /**
+ * Test write for replacing
+ */
+ public function testWriteReplace() {
+ $r = new Slim_Http_Response('Foo');
+ $r->write('Bar', true);
+ $this->assertEquals('Bar', $r->body());
}
/**
* Test finalize
- *
- * Pre-conditions:
- * Case A: Response status is 200
- * Case B: Response status is 204
- * Case C: Response status is 304
- *
- * Post-conditions:
- * Case A: Response has body and content-length
- * Case B: Response does not have body and content-length
- * Case C: Response does not have body and content-length
*/
public function testFinalize() {
- //Case A
- $r1 = new Slim_Http_Response(new Slim_Http_Request());
- $r1->body('body1');
- $r1->finalize();
- $this->assertEquals('body1', $r1->body());
- $this->assertEquals(5, $r1->header('Content-Length'));
-
- //Case B
- $r2 = new Slim_Http_Response(new Slim_Http_Request());
- $r2->body('body2');
- $r2->status(204);
- $r2->finalize();
- $this->assertEquals('', $r2->body());
- $this->assertNull($r2->header('Content-Type'));
-
- //Case C
- $r3 = new Slim_Http_Response(new Slim_Http_Request());
- $r3->body('body3');
- $r3->status(304);
- $r3->finalize();
- $this->assertEquals('', $r3->body());
- $this->assertNull($r3->header('Content-Type'));
- }
-
- /**
- * Test get messages for code
- *
- * Pre-conditions:
- * Case A: Status = 200
- * Case B: Status = 304
- * Case C: Status = 420 //Fake
- *
- * Post-conditions:
- * Case A: Message = '200 OK'
- * Case B: Message = '304 Not Modified'
- * Case C: Message = NULL
- */
- public function testGetMessageForCode() {
- //Case A
- $this->assertEquals('200 OK', Slim_Http_Response::getMessageForCode(200));
+ $r = new Slim_Http_Response();
+ $r->status(404);
+ $r['Content-Type'] = 'application/json';
+ $r->write('Foo');
+ $result = $r->finalize();
+ $this->assertEquals(3, count($result));
+ $this->assertEquals(404, $result[0]);
+ $this->assertFalse(is_null($result[1]['Content-Length']));
+ $this->assertFalse(is_null($result[1]['Content-Type']));
+ }
+
+ /**
+ * Test finalize
+ */
+ public function testFinalizeWithoutBody() {
+ $r = new Slim_Http_Response();
+ $r->status(204);
+ $r['Content-Type'] = 'application/json';
+ $r->write('Foo');
+ $result = $r->finalize();
+ $this->assertEquals(3, count($result));
+ $this->assertEquals('', $result[2]);
+ }
+
+ /**
+ * Test set cookie with only name and value
+ */
+ public function testSetCookieWithNameAndValue() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', 'bar');
+ $this->assertEquals('foo=bar', $r['Set-Cookie']);
+ }
- //Case B
- $this->assertEquals('304 Not Modified', Slim_Http_Response::getMessageForCode(304));
+ /**
+ * Test set multiple cookies with only name and value
+ */
+ public function testSetMultipleCookiesWithNameAndValue() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', 'bar');
+ $r->setCookie('abc', '123');
+ $this->assertEquals("foo=bar\nabc=123", $r['Set-Cookie']);
+ }
- //Case C
- $this->assertNull(Slim_Http_Response::getMessageForCode(420));
+ /**
+ * Test set cookie only name and value and expires (as int)
+ */
+ public function testSetMultipleCookiesWithNameAndValueAndExpiresAsInt() {
+ $now = time();
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'expires' => $now
+ ));
+ $this->assertEquals("foo=bar; expires=" . gmdate('D, d-M-Y H:i:s e', $now), $r['Set-Cookie']);
}
/**
- * Test can have body
- *
- * Pre-conditions:
- * Case A: Status code = 100
- * Case B: Status code = 200
- * Case C: Status code = 204
- * Case D: Status code = 304
- *
- * Post-conditions:
- * Case A: false
- * Case B: true
- * Case C: false
- * Case D: false
+ * Test set cookie with only name and value and expires (as string)
*/
- public function testCanHaveBody() {
- $r1 = new Slim_Http_Response(new Slim_Http_Request());
+ public function testSetMultipleCookiesWithNameAndValueAndExpiresAsString() {
+ $expires = 'next Tuesday';
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'expires' => $expires
+ ));
+ $this->assertEquals("foo=bar; expires=" . gmdate('D, d-M-Y H:i:s e', strtotime($expires)), $r['Set-Cookie']);
+ }
- //Case A
+ /**
+ * Test set cookie with name, value, domain
+ */
+ public function testSetCookieWithNameAndValueAndDomain() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'domain' => '.slimframework.com'
+ ));
+ $this->assertEquals('foo=bar; domain=.slimframework.com', $r['Set-Cookie']);
+ }
+
+ /**
+ * Test set cookie with name, value, domain, path
+ */
+ public function testSetCookieWithNameAndValueAndDomainAndPath() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'domain' => '.slimframework.com',
+ 'path' => '/foo'
+ ));
+ $this->assertEquals($r['Set-Cookie'], 'foo=bar; domain=.slimframework.com; path=/foo');
+ }
+
+ /**
+ * Test set cookie with only name and value and secure flag
+ */
+ public function testSetCookieWithNameAndValueAndSecureFlag() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'secure' => true
+ ));
+ $this->assertEquals('foo=bar; secure', $r['Set-Cookie']);
+ }
+
+ /**
+ * Test set cookie with only name and value and secure flag (as non-truthy)
+ */
+ public function testSetCookieWithNameAndValueAndSecureFlagAsNonTruthy() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'secure' => 0
+ ));
+ $this->assertEquals('foo=bar', $r['Set-Cookie']);
+ }
+
+ /**
+ * Test set cookie with only name and value and httponly flag
+ */
+ public function testSetCookieWithNameAndValueAndHttpOnlyFlag() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'httponly' => true
+ ));
+ $this->assertEquals('foo=bar; HttpOnly', $r['Set-Cookie']);
+ }
+
+ /**
+ * Test set cookie with only name and value and httponly flag (as non-truthy)
+ */
+ public function testSetCookieWithNameAndValueAndHttpOnlyFlagAsNonTruthy() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'httponly' => 0
+ ));
+ $this->assertEquals('foo=bar', $r['Set-Cookie']);
+ }
+
+ /*
+ * Test delete cookie by name
+ */
+ public function testDeleteCookieByName() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', 'bar');
+ $r->setCookie('abc', '123');
+ $r->deleteCookie('foo');
+ $this->assertEquals(1, preg_match("@abc=123\nfoo=; expires=@", $r['Set-Cookie']));
+ }
+
+ /*
+ * Test delete cookie by name and domain
+ */
+ public function testDeleteCookieByNameAndDomain1() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', 'bar'); //Note: This does not have domain associated with it
+ $r->setCookie('abc', '123');
+ $r->deleteCookie('foo', array('domain' => '.slimframework.com')); //This SHOULD NOT remove the `foo` cookie
+ $this->assertEquals(1, preg_match("@foo=bar\nabc=123\nfoo=; domain=.slimframework.com; expires=@", $r['Set-Cookie']));
+ }
+
+ /*
+ * Test delete cookie by name and domain
+ */
+ public function testDeleteCookieByNameAndDomain2() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', array(
+ 'value' => 'bar',
+ 'domain' => '.slimframework.com' //Note: This does have domain associated with it
+ ));
+ $r->setCookie('abc', '123');
+ $r->deleteCookie('foo', array('domain' => '.slimframework.com')); //This SHOULD remove the `foo` cookie
+ $this->assertEquals(1, preg_match("@abc=123\nfoo=; domain=.slimframework.com; expires=@", $r['Set-Cookie']));
+ }
+
+ /**
+ * Test delete cookie by name and custom props
+ */
+ public function testDeleteCookieByNameAndCustomProps() {
+ $r = new Slim_Http_Response();
+ $r->setCookie('foo', 'bar');
+ $r->setCookie('abc', '123');
+ $r->deleteCookie('foo', array(
+ 'secure' => true,
+ 'httponly' => true
+ ));
+ $this->assertEquals(1, preg_match("@abc=123\nfoo=; expires=.*; secure; HttpOnly@", $r['Set-Cookie']));
+ }
+
+ /**
+ * Test redirect
+ */
+ public function testRedirect() {
+ $r = new Slim_Http_Response();
+ $r->redirect('/foo');
+ $this->assertEquals(302, $r->status());
+ $this->assertEquals('/foo', $r['Location']);
+ }
+
+ /**
+ * Test redirect with custom status
+ */
+ public function testRedirectWithCustomStatus() {
+ $r = new Slim_Http_Response();
+ $r->redirect('/foo', 307);
+ $this->assertEquals(307, $r->status());
+ $this->assertEquals('/foo', $r['Location']);
+ }
+
+ /**
+ * Test isEmpty
+ */
+ public function testIsEmpty() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
+ $r1->status(404);
+ $r2->status(201);
+ $this->assertFalse($r1->isEmpty());
+ $this->assertTrue($r2->isEmpty());
+ }
+
+ /**
+ * Test isClientError
+ */
+ public function testIsClientError() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
+ $r1->status(404);
+ $r2->status(500);
+ $this->assertTrue($r1->isClientError());
+ $this->assertFalse($r2->isClientError());
+ }
+
+ /**
+ * Test isForbidden
+ */
+ public function testIsForbidden() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
+ $r1->status(403);
+ $r2->status(500);
+ $this->assertTrue($r1->isForbidden());
+ $this->assertFalse($r2->isForbidden());
+ }
+
+ /**
+ * Test isInformational
+ */
+ public function testIsInformational() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
$r1->status(100);
- $this->assertFalse($r1->canHaveBody());
+ $r2->status(200);
+ $this->assertTrue($r1->isInformational());
+ $this->assertFalse($r2->isInformational());
+ }
+
+ /**
+ * Test isInformational
+ */
+ public function testIsNotFound() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
+ $r1->status(404);
+ $r2->status(200);
+ $this->assertTrue($r1->isNotFound());
+ $this->assertFalse($r2->isNotFound());
+ }
- //Case B
+ /**
+ * Test isOk
+ */
+ public function testIsOk() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
$r1->status(200);
- $this->assertTrue($r1->canHaveBody());
+ $r2->status(201);
+ $this->assertTrue($r1->isOk());
+ $this->assertFalse($r2->isOk());
+ }
- //Case C
- $r1->status(204);
- $this->assertFalse($r1->canHaveBody());
+ /**
+ * Test isSuccessful
+ */
+ public function testIsSuccessful() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
+ $r3 = new Slim_Http_Response();
+ $r1->status(200);
+ $r2->status(201);
+ $r3->status(302);
+ $this->assertTrue($r1->isSuccessful());
+ $this->assertTrue($r2->isSuccessful());
+ $this->assertFalse($r3->isSuccessful());
+ }
+
+ /**
+ * Test isRedirect
+ */
+ public function testIsRedirect() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
+ $r1->status(307);
+ $r2->status(304);
+ $this->assertTrue($r1->isRedirect());
+ $this->assertFalse($r2->isRedirect());
+ }
+
+ /**
+ * Test isRedirection
+ */
+ public function testIsRedirection() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
+ $r3 = new Slim_Http_Response();
+ $r1->status(307);
+ $r2->status(304);
+ $r3->status(200);
+ $this->assertTrue($r1->isRedirection());
+ $this->assertTrue($r2->isRedirection());
+ $this->assertFalse($r3->isRedirection());
+ }
- //Case D
- $r1->status(304);
- $this->assertFalse($r1->canHaveBody());
+ /**
+ * Test isServerError
+ */
+ public function testIsServerError() {
+ $r1 = new Slim_Http_Response();
+ $r2 = new Slim_Http_Response();
+ $r1->status(500);
+ $r2->status(400);
+ $this->assertTrue($r1->isServerError());
+ $this->assertFalse($r2->isServerError());
}
/**
- * Test sets and gets CookieJar
+ * Test offset exists and offset get
*/
- public function testSetsAndGetsCookieJar() {
- $r = new Slim_Http_Response(new Slim_Http_Request());
- $cj = new Slim_Http_CookieJar('secret');
- $r->setCookieJar($cj);
- $this->assertSame($cj, $r->getCookieJar());
+ public function testOffsetExistsAndGet() {
+ $r = new Slim_Http_Response();
+ $this->assertFalse(empty($r['Content-Type']));
+ $this->assertNull($r['foo']);
}
/**
- * Test default HTTP version
+ * Test iteration
*/
- public function testDefaultHttpVersion() {
- $r = new Slim_Http_Response(new Slim_Http_Request());
- $this->assertEquals('1.1', $r->httpVersion());
+ public function testIteration() {
+ $h = new Slim_Http_Response();
+ $output = '';
+ foreach ( $h as $key => $value ) {
+ $output .= $key . $value;
+ }
+ $this->assertEquals('content-typetext/htmlcontent-length0', $output);
}
/**
- * Test can set HTTP version
+ * Test countable
*/
- public function testCanSetValidHttpVersion() {
- $r = new Slim_Http_Response(new Slim_Http_Request());
- $r->httpVersion('1.0');
- $this->assertEquals('1.0', $r->httpVersion());
- $r->httpVersion('1.1');
- $this->assertEquals('1.1', $r->httpVersion());
+ public function testCountable() {
+ $r1 = new Slim_Http_Response();
+ $this->assertEquals(2, count($r1)); //Content-Length and Content-Type
+ }
+
+ /**
+ * Test message for code when message exists
+ */
+ public function testMessageForCode() {
+ $this->assertEquals('200 OK', Slim_Http_Response::getMessageForCode(200));
}
/**
- * Test can set HTTP version
+ * Test message for code when message exists
*/
- public function testCannotSetInvalidHttpVersion() {
- $this->setExpectedException('InvalidArgumentException');
- $r = new Slim_Http_Response(new Slim_Http_Request());
- $r->httpVersion('1.2');
+ public function testMessageForCodeWithInvalidCode() {
+ $this->assertNull(Slim_Http_Response::getMessageForCode(600));
}
-}
+}
+?>

0 comments on commit c22aaf0

Please sign in to comment.