100% coverage for net classes

pull/501/head
n0nag0n 1 year ago
parent 39f61b3d74
commit 7b15d2cfca

@ -202,7 +202,7 @@ class Response
/** /**
* Sets caching headers for the response. * Sets caching headers for the response.
* *
* @param int|string|false $expires Expiration time * @param int|string|false $expires Expiration time as time() or as strtotime() string value
* *
* @return Response Self reference * @return Response Self reference
*/ */
@ -237,7 +237,8 @@ class Response
{ {
// Send status code header // Send status code header
if (false !== strpos(\PHP_SAPI, 'cgi')) { if (false !== strpos(\PHP_SAPI, 'cgi')) {
header( // @codeCoverageIgnoreStart
$this->setRealHeader(
sprintf( sprintf(
'Status: %d %s', 'Status: %d %s',
$this->status, $this->status,
@ -245,8 +246,9 @@ class Response
), ),
true true
); );
// @codeCoverageIgnoreEnd
} else { } else {
header( $this->setRealHeader(
sprintf( sprintf(
'%s %d %s', '%s %d %s',
$_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1', $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1',
@ -262,10 +264,10 @@ class Response
foreach ($this->headers as $field => $value) { foreach ($this->headers as $field => $value) {
if (\is_array($value)) { if (\is_array($value)) {
foreach ($value as $v) { foreach ($value as $v) {
header($field . ': ' . $v, false); $this->setRealHeader($field . ': ' . $v, false);
} }
} else { } else {
header($field . ': ' . $value); $this->setRealHeader($field . ': ' . $value);
} }
} }
@ -274,13 +276,27 @@ class Response
$length = $this->getContentLength(); $length = $this->getContentLength();
if ($length > 0) { if ($length > 0) {
header('Content-Length: ' . $length); $this->setRealHeader('Content-Length: ' . $length);
} }
} }
return $this; return $this;
} }
/**
* Sets a real header. Mostly used for test mocking.
*
* @param string $header_string The header string you would pass to header()
* @param bool $replace The optional replace parameter indicates whether the header should replace a previous similar header, or add a second header of the same type. By default it will replace, but if you pass in false as the second argument you can force multiple headers of the same type.
* @param int $response_code The response code to send
* @return self
* @codeCoverageIgnore
*/
public function setRealHeader(string $header_string, bool $replace = true, int $response_code = 0): self {
header($header_string, $replace, $response_code);
return $this;
}
/** /**
* Gets the content length. * Gets the content length.
* *
@ -294,7 +310,7 @@ class Response
} }
/** /**
* Gets whether response was sent. * Gets whether response body was sent.
*/ */
public function sent(): bool public function sent(): bool
{ {
@ -307,11 +323,11 @@ class Response
public function send(): void public function send(): void
{ {
if (ob_get_length() > 0) { if (ob_get_length() > 0) {
ob_end_clean(); ob_end_clean(); // @codeCoverageIgnore
} }
if (!headers_sent()) { if (!headers_sent()) {
$this->sendHeaders(); $this->sendHeaders(); // @codeCoverageIgnore
} }
echo $this->body; echo $this->body;

@ -0,0 +1,238 @@
<?php
/**
* Flight: An extensible micro-framework.
*
* @copyright Copyright (c) 2012, Mike Cao <mike@mikecao.com>
* @license MIT, http://flightphp.com/license
*/
use flight\net\Request;
use flight\net\Response;
use flight\util\Collection;
class ResponseTest extends PHPUnit\Framework\TestCase
{
protected function setUp(): void
{
$_SERVER = [];
$_REQUEST = [];
// $_SERVER['REQUEST_URI'] = '/';
// $_SERVER['SCRIPT_NAME'] = '/index.php';
// $_SERVER['REQUEST_METHOD'] = 'GET';
// $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
// $_SERVER['REMOTE_ADDR'] = '8.8.8.8';
// $_SERVER['HTTP_X_FORWARDED_FOR'] = '32.32.32.32';
// $_SERVER['HTTP_HOST'] = 'example.com';
// $_SERVER['CONTENT_TYPE'] = '';
$_GET = [];
$_POST = [];
$_COOKIE = [];
$_FILES = [];
// $this->request = new Request();
}
protected function tearDown(): void {
unset($_REQUEST);
unset($_SERVER);
}
public function testStatusDefault() {
$response = new Response();
$this->assertSame(200, $response->status());
}
public function testStatusValidCode() {
$response = new Response();
$response->status(200);
$this->assertEquals(200, $response->status());
}
public function testStatusInvalidCode() {
$response = new Response();
$this->expectException(Exception::class);
$this->expectExceptionMessage('Invalid status code.');
$response->status(999);
}
public function testStatusReturnObject() {
$response = new Response();
$this->assertEquals($response, $response->status(200));
}
public function testHeaderSingle() {
$response = new Response();
$response->header('Content-Type', 'text/html');
$this->assertEquals(['Content-Type' => 'text/html'], $response->headers());
}
public function testHeaderSingleKeepCaseSensitive() {
$response = new Response();
$response->header('content-type', 'text/html');
$response->header('x-test', 'test');
$this->assertEquals(['content-type' => 'text/html', 'x-test' => 'test'], $response->headers());
}
public function testHeaderArray() {
$response = new Response();
$response->header(['Content-Type' => 'text/html', 'X-Test' => 'test']);
$this->assertEquals(['Content-Type' => 'text/html', 'X-Test' => 'test'], $response->headers());
}
public function testHeaderReturnObject() {
$response = new Response();
$this->assertEquals($response, $response->header('Content-Type', 'text/html'));
}
public function testWrite() {
$response = new class extends Response {
public function getBody() {
return $this->body;
}
};
$response->write('test');
$this->assertEquals('test', $response->getBody());
}
public function testWriteEmptyString() {
$response = new class extends Response {
public function getBody() {
return $this->body;
}
};
$response->write('');
$this->assertEquals('', $response->getBody());
}
public function testWriteReturnObject() {
$response = new Response();
$this->assertEquals($response, $response->write('test'));
}
public function testClear() {
$response = new class extends Response {
public function getBody() {
return $this->body;
}
};
$response->write('test');
$response->status(404);
$response->header('Content-Type', 'text/html');
$response->clear();
$this->assertEquals('', $response->getBody());
$this->assertEquals(200, $response->status());
$this->assertEquals([], $response->headers());
}
public function testCacheSimple() {
$response = new Response();
$cache_time = time() + 60;
$response->cache($cache_time);
$this->assertEquals([
'Expires' => gmdate('D, d M Y H:i:s', $cache_time) . ' GMT',
'Cache-Control' => 'max-age=60'
], $response->headers());
}
public function testCacheSimpleWithString() {
$response = new Response();
$cache_time = time() + 60;
$response->cache('now +60 seconds');
$this->assertEquals([
'Expires' => gmdate('D, d M Y H:i:s', $cache_time) . ' GMT',
'Cache-Control' => 'max-age=60'
], $response->headers());
}
public function testCacheSimpleWithPragma() {
$response = new Response();
$cache_time = time() + 60;
$response->header('Pragma', 'no-cache');
$response->cache($cache_time);
$this->assertEquals([
'Expires' => gmdate('D, d M Y H:i:s', $cache_time) . ' GMT',
'Cache-Control' => 'max-age=60'
], $response->headers());
}
public function testCacheFalseExpiresValue() {
$response = new Response();
$response->cache(false);
$this->assertEquals([
'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
'Cache-Control' => [
'no-store, no-cache, must-revalidate',
'post-check=0, pre-check=0',
'max-age=0',
],
'Pragma' => 'no-cache'
], $response->headers());
}
public function testSendHeadersRegular() {
$response = new class extends Response {
protected $test_sent_headers = [];
protected array $headers = [
'Cache-Control' => [
'no-store, no-cache, must-revalidate',
'post-check=0, pre-check=0',
'max-age=0',
]
];
public function setRealHeader(string $header_string, bool $replace = true, int $response_code = 0): Response
{
$this->test_sent_headers[] = $header_string;
return $this;
}
public function getSentHeaders(): array
{
return $this->test_sent_headers;
}
};
$response->header('Content-Type', 'text/html');
$response->header('X-Test', 'test');
$response->write('Something');
$response->sendHeaders();
$sent_headers = $response->getSentHeaders();
$this->assertEquals([
'HTTP/1.1 200 OK',
'Cache-Control: no-store, no-cache, must-revalidate',
'Cache-Control: post-check=0, pre-check=0',
'Cache-Control: max-age=0',
'Content-Type: text/html',
'X-Test: test',
'Content-Length: 9'
], $sent_headers);
}
public function testSentDefault() {
$response = new Response();
$this->assertFalse($response->sent());
}
public function testSentTrue() {
$response = new class extends Response {
protected $test_sent_headers = [];
public function setRealHeader(string $header_string, bool $replace = true, int $response_code = 0): Response
{
$this->test_sent_headers[] = $header_string;
return $this;
}
};
$response->header('Content-Type', 'text/html');
$response->header('X-Test', 'test');
$response->write('Something');
$this->expectOutputString('Something');
$response->send();
$this->assertTrue($response->sent());
}
}
Loading…
Cancel
Save