Merge pull request #1047 from bcit-ci/testing

New Feature/HTTP Testing capabilities
This commit is contained in:
Lonnie Ezell 2018-05-25 23:22:40 -05:00 committed by GitHub
commit 34074ac247
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
148 changed files with 2520 additions and 961 deletions

View File

@ -1,6 +1,6 @@
<?php namespace Config;
require BASEPATH.'Config/AutoloadConfig.php';
require_once BASEPATH.'Config/AutoloadConfig.php';
/**
* -------------------------------------------------------------------

View File

@ -12,7 +12,8 @@
},
"autoload": {
"psr-4": {
"CodeIgniter\\": "system/"
"CodeIgniter\\": "system/",
"Psr\\Log\\": "system/ThirdParty/PSR/Log/"
}
},
"require": {

View File

@ -344,16 +344,15 @@ trait ResponseTrait
return $data;
}
// Determine correct response type through content negotiation
$config = new Format();
$format = $this->request->negotiate('media', $config->supportedResponseFormats, true);
$this->response->setContentType($format);
// if we don't have a formatter, make one
if ( ! isset($this->formatter))
{
$config = new Format();
// Determine correct response type through content negotiation
$format = $this->request->negotiate('media', $config->supportedResponseFormats, true);
$this->response->setContentType($format);
// if no formatter, use the default
$this->formatter = $config->getFormatter($format);
}

View File

@ -36,6 +36,7 @@
* @filesource
*/
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\Request;
use Config\Services;
use Config\Cache;
use CodeIgniter\HTTP\URI;
@ -180,8 +181,12 @@ class CodeIgniter
* makes all of the pieces work together.
*
* @param \CodeIgniter\Router\RouteCollectionInterface $routes
* @param bool $returnResponse
*
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function run(RouteCollectionInterface $routes = null)
public function run(RouteCollectionInterface $routes = null, bool $returnResponse = false)
{
$this->startBenchmark();
@ -201,7 +206,7 @@ class CodeIgniter
try
{
$this->handleRequest($routes, $cacheConfig);
return $this->handleRequest($routes, $cacheConfig, $returnResponse);
} catch (Router\RedirectException $e)
{
$logger = Services::logger();
@ -225,8 +230,11 @@ class CodeIgniter
*
* @param \CodeIgniter\Router\RouteCollectionInterface $routes
* @param $cacheConfig
* @param bool $returnResponse
*
* @throws \CodeIgniter\Filters\Exceptions\FilterException
*/
protected function handleRequest(RouteCollectionInterface $routes = null, $cacheConfig)
protected function handleRequest(RouteCollectionInterface $routes = null, $cacheConfig, bool $returnResponse = false)
{
$this->tryToRouteIt($routes);
@ -257,6 +265,11 @@ class CodeIgniter
// Handle any redirects
if ($returned instanceof RedirectResponse)
{
if ($returnResponse)
{
return $returned;
}
$this->callExit(EXIT_SUCCESS);
}
@ -279,12 +292,17 @@ class CodeIgniter
unset($uri);
$this->sendResponse();
if (! $returnResponse)
{
$this->sendResponse();
}
//--------------------------------------------------------------------
// Is there a post-system event?
//--------------------------------------------------------------------
Events::trigger('post_system');
return $this->response;
}
//--------------------------------------------------------------------
@ -358,6 +376,23 @@ class CodeIgniter
//--------------------------------------------------------------------
/**
* Sets a Request object to be used for this request.
* Used when running certain tests.
*
* @param \CodeIgniter\HTTP\Request $request
*
* @return \CodeIgniter\CodeIgniter
*/
public function setRequest(Request $request)
{
$this->request = $request;
return $this;
}
//--------------------------------------------------------------------
/**
* Get our Request object, (either IncomingRequest or CLIRequest)
* and set the server protocol based on the information provided
@ -365,6 +400,11 @@ class CodeIgniter
*/
protected function getRequestObject()
{
if ($this->request instanceof Request)
{
return;
}
if (is_cli() && ! (ENVIRONMENT == 'testing'))
{
$this->request = Services::clirequest($this->config);

View File

@ -435,7 +435,7 @@ if ( ! function_exists('log_message'))
// for asserting that logs were called in the test code.
if (ENVIRONMENT == 'testing')
{
$logger = new \CodeIgniter\Log\TestLogger(new \Config\Logger());
$logger = new \Tests\Support\Log\TestLogger(new \Config\Logger());
return $logger->log($level, $message, $context);
}

View File

@ -91,7 +91,7 @@ class AutoloadConfig
if (isset($_SERVER['CI_ENVIRONMENT']) && $_SERVER['CI_ENVIRONMENT'] === 'testing')
{
$this->psr4['Tests\Support'] = BASEPATH . '../tests/_support/';
$this->psr4['Tests\Support'] = BASEPATH . '../tests/_support';
}
/**

View File

@ -37,7 +37,9 @@
*/
use CodeIgniter\Database\ConnectionInterface;
use CodeIgniter\Database\MigrationRunner;
use CodeIgniter\HTTP\URI;
use CodeIgniter\View\RendererInterface;
use Config\App;
/**
* Services Configuration file.
@ -546,7 +548,7 @@ class Services
if ( ! is_object($config))
{
$config = new \Config\App();
$config = new App();
}
return new \CodeIgniter\HTTP\IncomingRequest(

View File

@ -410,6 +410,11 @@ class Toolbar
{
self::$request = Services::request();
if(ENVIRONMENT == 'testing')
{
return;
}
// If the request contains '?debugbar then we're
// simply returning the loading script
if (self::$request->getGet('debugbar') !== null)

View File

@ -1,3 +1,4 @@
<?php if (ENVIRONMENT != 'testing') : ?>
document.addEventListener('DOMContentLoaded', loadDoc, false);
function loadDoc(time) {
@ -56,3 +57,4 @@ function newXHR() {
}
window.XMLHttpRequest = newXHR;
<?php endif; ?>

View File

@ -290,7 +290,7 @@ class Events
*
* @param string $path
*/
public function setFile(string $path)
public static function setFile(string $path)
{
self::$eventsFile = $path;
}

View File

@ -322,7 +322,7 @@ class IncomingRequest extends Request
*/
public function getVar($index = null, $filter = null, $flags = null)
{
return $this->fetchGlobal(INPUT_REQUEST, $index, $filter, $flags);
return $this->fetchGlobal('request', $index, $filter, $flags);
}
//--------------------------------------------------------------------
@ -375,7 +375,7 @@ class IncomingRequest extends Request
*/
public function getGet($index = null, $filter = null, $flags = null)
{
return $this->fetchGlobal(INPUT_GET, $index, $filter, $flags);
return $this->fetchGlobal('get', $index, $filter, $flags);
}
//--------------------------------------------------------------------
@ -391,7 +391,7 @@ class IncomingRequest extends Request
*/
public function getPost($index = null, $filter = null, $flags = null)
{
return $this->fetchGlobal(INPUT_POST, $index, $filter, $flags);
return $this->fetchGlobal('post', $index, $filter, $flags);
}
//--------------------------------------------------------------------
@ -445,7 +445,7 @@ class IncomingRequest extends Request
*/
public function getCookie($index = null, $filter = null, $flags = null)
{
return $this->fetchGlobal(INPUT_COOKIE, $index, $filter, $flags);
return $this->fetchGlobal('cookie', $index, $filter, $flags);
}
//--------------------------------------------------------------------
@ -478,7 +478,9 @@ class IncomingRequest extends Request
// If the session hasn't been started, or no
// data was previously saved, we're done.
if (empty($_SESSION['_ci_old_input']))
{
return;
}
// Check for the value in the POST array first.
if (isset($_SESSION['_ci_old_input']['post'][$key]))
@ -616,7 +618,7 @@ class IncomingRequest extends Request
break;
case 'PATH_INFO':
default:
$path = $_SERVER[$protocol] ?? $this->parseRequestURI();
$path = $this->fetchGlobal('server', $protocol) ?? $this->parseRequestURI();
break;
}

View File

@ -362,7 +362,7 @@ class Message
*/
public function getProtocolVersion(): string
{
return $this->protocolVersion;
return $this->protocolVersion ?? '1.1';
}
//--------------------------------------------------------------------

View File

@ -64,6 +64,13 @@ class Request extends Message implements RequestInterface
*/
protected $method;
/**
* Stores values we've retrieved from
* PHP globals.
* @var array
*/
protected $globals = [];
//--------------------------------------------------------------------
/**
@ -281,7 +288,7 @@ class Request extends Message implements RequestInterface
*/
public function getServer($index = null, $filter = null, $flags = null)
{
return $this->fetchGlobal(INPUT_SERVER, $index, $filter, $flags);
return $this->fetchGlobal('server', $index, $filter, $flags);
}
//--------------------------------------------------------------------
@ -297,7 +304,24 @@ class Request extends Message implements RequestInterface
*/
public function getEnv($index = null, $filter = null, $flags = null)
{
return $this->fetchGlobal(INPUT_ENV, $index, $filter, $flags);
return $this->fetchGlobal('env', $index, $filter, $flags);
}
//--------------------------------------------------------------------
/**
* Allows manually setting the value of PHP global, like $_GET, $_POST, etc.
*
* @param string $method
* @param $value
*
* @return $this
*/
public function setGlobal(string $method, $value)
{
$this->globals[$method] = $value;
return $this;
}
//--------------------------------------------------------------------
@ -312,45 +336,37 @@ class Request extends Message implements RequestInterface
*
* http://php.net/manual/en/filter.filters.sanitize.php
*
* @param int $type Input filter constant
* @param int $method Input filter constant
* @param string|array $index
* @param int $filter Filter constant
* @param null $flags
*
* @return mixed
*/
protected function fetchGlobal($type, $index = null, $filter = null, $flags = null )
public function fetchGlobal($method, $index = null, $filter = null, $flags = null )
{
$method = strtolower($method);
if (! isset($this->globals[$method]))
{
$this->populateGlobals($method);
}
// Null filters cause null values to return.
if (is_null($filter))
{
$filter = FILTER_DEFAULT;
}
$loopThrough = [];
switch ($type)
{
case INPUT_GET : $loopThrough = $_GET;
break;
case INPUT_POST : $loopThrough = $_POST;
break;
case INPUT_COOKIE : $loopThrough = $_COOKIE;
break;
case INPUT_SERVER : $loopThrough = $_SERVER;
break;
case INPUT_ENV : $loopThrough = $_ENV;
break;
case INPUT_REQUEST : $loopThrough = $_REQUEST;
break;
}
// If $index is null, it means that the whole input type array is requested
// Return all values when $index is null
if (is_null($index))
{
$values = [];
foreach ($loopThrough as $key => $value)
foreach ($this->globals[$method] as $key => $value)
{
$values[$key] = is_array($value) ? $this->fetchGlobal($type, $key, $filter, $flags) : filter_var($value, $filter, $flags);
$values[$key] = is_array($value)
? $this->fetchGlobal($method, $key, $filter, $flags)
: filter_var($value, $filter, $flags);
}
return $values;
@ -363,7 +379,7 @@ class Request extends Message implements RequestInterface
foreach ($index as $key)
{
$output[$key] = $this->fetchGlobal($type, $key, $filter, $flags);
$output[$key] = $this->fetchGlobal($method, $key, $filter, $flags);
}
return $output;
@ -372,7 +388,7 @@ class Request extends Message implements RequestInterface
// Does the index contain array notation?
if (($count = preg_match_all('/(?:^[^\[]+)|\[[^]]*\]/', $index, $matches)) > 1)
{
$value = $loopThrough;
$value = $this->globals[$method];
for ($i = 0; $i < $count; $i++)
{
$key = trim($matches[0][$i], '[]');
@ -393,14 +409,12 @@ class Request extends Message implements RequestInterface
}
}
// Due to issues with FastCGI and testing,
// we need to do these all manually instead
// of the simpler filter_input();
if (empty($value))
{
$value = $loopThrough[$index] ?? null;
$value = $this->globals[$method][$index] ?? null;
}
// Cannot filter these types of data automatically...
if (is_array($value) || is_object($value) || is_null($value))
{
return $value;
@ -410,4 +424,39 @@ class Request extends Message implements RequestInterface
}
//--------------------------------------------------------------------
/**
* Saves a copy of the current state of one of several PHP globals
* so we can retrieve them later.
*
* @param string $method
*/
protected function populateGlobals(string $method)
{
if (! isset($this->globals[$method]))
{
$this->globals[$method] = [];
}
// Don't populate ENV as it might contain
// sensitive data that we don't want to get logged.
switch($method)
{
case 'get':
$this->globals['get'] = $_GET;
break;
case 'post':
$this->globals['post'] = $_POST;
break;
case 'request':
$this->globals['request'] = $_REQUEST;
break;
case 'cookie':
$this->globals['cookie'] = $_COOKIE;
break;
case 'server':
$this->globals['server'] = $_SERVER;
break;
}
}
}

View File

@ -36,7 +36,9 @@
* @filesource
*/
use CodeIgniter\HTTP\Exceptions\HTTPException;
use CodeIgniter\Services;
use Config\App;
use Config\Format;
use Config\Mimes;
/**
@ -71,75 +73,75 @@ class Response extends Message implements ResponseInterface
*/
protected static $statusCodes = [
// 1xx: Informational
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing', // http://www.iana.org/go/rfc2518
103 => 'Early Hints', // http://www.ietf.org/rfc/rfc8297.txt
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing', // http://www.iana.org/go/rfc2518
103 => 'Early Hints', // http://www.ietf.org/rfc/rfc8297.txt
// 2xx: Success
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information', // 1.1
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status', // http://www.iana.org/go/rfc4918
208 => 'Already Reported', // http://www.iana.org/go/rfc5842
226 => 'IM Used', // 1.1; http://www.ietf.org/rfc/rfc3229.txt
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information', // 1.1
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status', // http://www.iana.org/go/rfc4918
208 => 'Already Reported', // http://www.iana.org/go/rfc5842
226 => 'IM Used', // 1.1; http://www.ietf.org/rfc/rfc3229.txt
// 3xx: Redirection
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found', // Formerly 'Moved Temporarily'
303 => 'See Other', // 1.1
304 => 'Not Modified',
305 => 'Use Proxy', // 1.1
306 => 'Switch Proxy', // No longer used
307 => 'Temporary Redirect', // 1.1
308 => 'Permanent Redirect', // 1.1; Experimental; http://www.ietf.org/rfc/rfc7238.txt
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found', // Formerly 'Moved Temporarily'
303 => 'See Other', // 1.1
304 => 'Not Modified',
305 => 'Use Proxy', // 1.1
306 => 'Switch Proxy', // No longer used
307 => 'Temporary Redirect', // 1.1
308 => 'Permanent Redirect', // 1.1; Experimental; http://www.ietf.org/rfc/rfc7238.txt
// 4xx: Client error
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
418 => "I'm a teapot", // April's Fools joke; http://www.ietf.org/rfc/rfc2324.txt
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
418 => "I'm a teapot", // April's Fools joke; http://www.ietf.org/rfc/rfc2324.txt
// 419 (Authentication Timeout) is a non-standard status code with unknown origin
421 => 'Misdirected Request', // http://www.iana.org/go/rfc7540 Section 9.1.2
422 => 'Unprocessable Entity', // http://www.iana.org/go/rfc4918
423 => 'Locked', // http://www.iana.org/go/rfc4918
424 => 'Failed Dependency', // http://www.iana.org/go/rfc4918
426 => 'Upgrade Required',
428 => 'Precondition Required', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
429 => 'Too Many Requests', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
431 => 'Request Header Fields Too Large', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
451 => 'Unavailable For Legal Reasons', // http://tools.ietf.org/html/rfc7725
499 => 'Client Closed Request', // http://lxr.nginx.org/source/src/http/ngx_http_request.h#0133
421 => 'Misdirected Request', // http://www.iana.org/go/rfc7540 Section 9.1.2
422 => 'Unprocessable Entity', // http://www.iana.org/go/rfc4918
423 => 'Locked', // http://www.iana.org/go/rfc4918
424 => 'Failed Dependency', // http://www.iana.org/go/rfc4918
426 => 'Upgrade Required',
428 => 'Precondition Required', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
429 => 'Too Many Requests', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
431 => 'Request Header Fields Too Large', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
451 => 'Unavailable For Legal Reasons', // http://tools.ietf.org/html/rfc7725
499 => 'Client Closed Request', // http://lxr.nginx.org/source/src/http/ngx_http_request.h#0133
// 5xx: Server error
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates', // 1.1; http://www.ietf.org/rfc/rfc2295.txt
507 => 'Insufficient Storage', // http://www.iana.org/go/rfc4918
508 => 'Loop Detected', // http://www.iana.org/go/rfc5842
510 => 'Not Extended', // http://www.ietf.org/rfc/rfc2774.txt
511 => 'Network Authentication Required', // http://www.ietf.org/rfc/rfc6585.txt
599 => 'Network Connect Timeout Error', // https://httpstatuses.com/599
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates', // 1.1; http://www.ietf.org/rfc/rfc2295.txt
507 => 'Insufficient Storage', // http://www.iana.org/go/rfc4918
508 => 'Loop Detected', // http://www.iana.org/go/rfc5842
510 => 'Not Extended', // http://www.ietf.org/rfc/rfc2774.txt
511 => 'Network Authentication Required', // http://www.ietf.org/rfc/rfc6585.txt
599 => 'Network Connect Timeout Error', // https://httpstatuses.com/599
];
/**
@ -206,6 +208,28 @@ class Response extends Message implements ResponseInterface
*/
protected $cookieHTTPOnly = false;
/**
* Stores all cookies that were set in the response.
*
* @var array
*/
protected $cookies = [];
/**
* If true, will not write output. Useful during testing.
*
* @var bool
*/
protected $pretend = false;
/**
* Type of format the body is in.
* Valid: html, json, xml
*
* @var string
*/
protected $bodyFormat = 'html';
//--------------------------------------------------------------------
/**
@ -222,14 +246,14 @@ class Response extends Message implements ResponseInterface
// Are we enforcing a Content Security Policy?
if ($config->CSPEnabled === true)
{
$this->CSP = new ContentSecurityPolicy(new \Config\ContentSecurityPolicy());
$this->CSP = new ContentSecurityPolicy(new \Config\ContentSecurityPolicy());
$this->CSPEnabled = true;
}
$this->cookiePrefix = $config->cookiePrefix;
$this->cookieDomain = $config->cookieDomain;
$this->cookiePath = $config->cookiePath;
$this->cookieSecure = $config->cookieSecure;
$this->cookiePrefix = $config->cookiePrefix;
$this->cookieDomain = $config->cookieDomain;
$this->cookiePath = $config->cookiePath;
$this->cookieSecure = $config->cookieSecure;
$this->cookieHTTPOnly = $config->cookieHTTPOnly;
// Default to an HTML Content-Type. Devs can override if needed.
@ -238,6 +262,20 @@ class Response extends Message implements ResponseInterface
//--------------------------------------------------------------------
/**
* Turns "pretend" mode on or off to aid in testing.
*
* @param bool $pretend
*
* @return $this
*/
public function pretend(bool $pretend = true)
{
$this->pretend = $pretend;
return $this;
}
/**
* Gets the response status code.
*
@ -284,14 +322,14 @@ class Response extends Message implements ResponseInterface
}
// Unknown and no message?
if ( ! array_key_exists($code, static::$statusCodes) && empty($reason))
if (! array_key_exists($code, static::$statusCodes) && empty($reason))
{
throw HTTPException::forUnkownStatusCode($code);
}
$this->statusCode = $code;
if ( ! empty($reason))
if (! empty($reason))
{
$this->reason = $reason;
}
@ -339,7 +377,7 @@ class Response extends Message implements ResponseInterface
{
$date->setTimezone(new \DateTimeZone('UTC'));
$this->setHeader('Date', $date->format('D, d M Y H:i:s') . ' GMT');
$this->setHeader('Date', $date->format('D, d M Y H:i:s').' GMT');
return $this;
}
@ -360,7 +398,7 @@ class Response extends Message implements ResponseInterface
// add charset attribute if not already there and provided as parm
if ((strpos($mime, 'charset=') < 1) && ! empty($charset))
{
$mime .= '; charset=' . $charset;
$mime .= '; charset='.$charset;
}
$this->removeHeader('Content-Type'); // replace existing content type
@ -370,6 +408,114 @@ class Response extends Message implements ResponseInterface
}
//--------------------------------------------------------------------
/**
* Converts the $body into JSON and sets the Content Type header.
*
* @param $body
*
* @return $this
*/
public function setJSON($body)
{
$this->body = $this->formatBody($body, 'json');
return $this;
return $this;
}
//--------------------------------------------------------------------
/**
* Returns the current body, converted to JSON is it isn't already.
*
* @return mixed|string
*/
public function getJSON()
{
$body = $this->body;
if ($this->bodyFormat != 'json')
{
$config = new Format();
$formatter = $config->getFormatter('application/json');
$body = $formatter->format($body);
}
return $body ?: null;
}
//--------------------------------------------------------------------
/**
* Converts $body into XML, and sets the correct Content-Type.
*
* @param $body
*
* @return $this
*/
public function setXML($body)
{
$this->body = $this->formatBody($body, 'xml');
return $this;
}
//--------------------------------------------------------------------
/**
* Retrieves the current body into XML and returns it.
*
* @return mixed|string
*/
public function getXML()
{
$body = $this->body;
if ($this->bodyFormat != 'xml')
{
$config = new Format();
$formatter = $config->getFormatter('application/xml');
$body = $formatter->format($body);
}
return $body;
}
//--------------------------------------------------------------------
/**
* Handles conversion of the of the data into the appropriate format,
* and sets the correct Content-Type header for our response.
*
* @param $body
* @param string $format Valid: json, xml
*
* @return mixed
*/
protected function formatBody($body, string $format)
{
$mime = "application/{$format}";
$this->setContentType($mime);
$this->bodyFormat = $format;
// Nothing much to do for a string...
if (! is_string($body))
{
$config = new Format();
$formatter = $config->getFormatter($mime);
$body = $formatter->format($body);
}
return $body;
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Cache Control Methods
//
@ -468,7 +614,7 @@ class Response extends Message implements ResponseInterface
if ($date instanceof \DateTime)
{
$date->setTimezone(new \DateTimeZone('UTC'));
$this->setHeader('Last-Modified', $date->format('D, d M Y H:i:s') . ' GMT');
$this->setHeader('Last-Modified', $date->format('D, d M Y H:i:s').' GMT');
}
elseif (is_string($date))
{
@ -499,6 +645,7 @@ class Response extends Message implements ResponseInterface
$this->sendHeaders();
$this->sendBody();
$this->sendCookies();
return $this;
}
@ -526,12 +673,13 @@ class Response extends Message implements ResponseInterface
}
// HTTP Status
header(sprintf('HTTP/%s %s %s', $this->protocolVersion, $this->statusCode, $this->reason), true, $this->statusCode);
header(sprintf('HTTP/%s %s %s', $this->protocolVersion, $this->statusCode, $this->reason), true,
$this->statusCode);
// Send all of our headers
foreach ($this->getHeaders() as $name => $values)
{
header($name . ': ' . $this->getHeaderLine($name), false, $this->statusCode);
header($name.': '.$this->getHeaderLine($name), false, $this->statusCode);
}
return $this;
@ -553,6 +701,16 @@ class Response extends Message implements ResponseInterface
//--------------------------------------------------------------------
/**
* Grabs the current body.
*
* @return mixed|string
*/
public function getBody()
{
return $this->body;
}
/**
* Perform a redirect to a new URL, in two flavors: header or location.
*
@ -566,7 +724,8 @@ class Response extends Message implements ResponseInterface
public function redirect(string $uri, string $method = 'auto', int $code = null)
{
// IIS environment likely? Use 'refresh' for better compatibility
if ($method === 'auto' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false)
if ($method === 'auto' && isset($_SERVER['SERVER_SOFTWARE'])
&& strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false)
{
$method = 'refresh';
}
@ -574,8 +733,9 @@ class Response extends Message implements ResponseInterface
{
if (isset($_SERVER['SERVER_PROTOCOL'], $_SERVER['REQUEST_METHOD']) && $this->getProtocolVersion() >= 1.1)
{
$code = ($_SERVER['REQUEST_METHOD'] !== 'GET') ? 303 // reference: http://en.wikipedia.org/wiki/Post/Redirect/Get
: 307;
$code = ($_SERVER['REQUEST_METHOD'] !== 'GET') ? 303
// reference: http://en.wikipedia.org/wiki/Post/Redirect/Get
: 307;
}
else
{
@ -586,7 +746,7 @@ class Response extends Message implements ResponseInterface
switch ($method)
{
case 'refresh':
$this->setHeader('Refresh', '0;url=' . $uri);
$this->setHeader('Refresh', '0;url='.$uri);
break;
default:
$this->setHeader('Location', $uri);
@ -618,9 +778,15 @@ class Response extends Message implements ResponseInterface
* @param bool|false $httponly Whether only make the cookie accessible via HTTP (no javascript)
*/
public function setCookie(
$name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = false, $httponly = false
)
{
$name,
$value = '',
$expire = '',
$domain = '',
$path = '/',
$prefix = '',
$secure = false,
$httponly = false
) {
if (is_array($name))
{
// always leave 'name' in last place, as the loop will break otherwise, due to $$item
@ -658,20 +824,108 @@ class Response extends Message implements ResponseInterface
$httponly = $this->cookieHTTPOnly;
}
if ( ! is_numeric($expire))
if (! is_numeric($expire))
{
$expire = time() - 86500;
$expire = time()-86500;
}
else
{
$expire = ($expire > 0) ? time() + $expire : 0;
$expire = ($expire > 0) ? time()+$expire : 0;
}
setcookie($prefix . $name, $value, $expire, $path, $domain, $secure, $httponly);
$this->cookies[] = [
'name' => $prefix.$name,
'value' => $value,
'expires' => $expire,
'path' => $path,
'domain' => $domain,
'secure' => $secure,
'httponly' => $httponly,
];
return $this;
}
//--------------------------------------------------------------------
/**
* Checks to see if the Response has a specified cookie or not.
*
* @param string $name
* @param null $value
* @param string $prefix
*
* @return bool
*/
public function hasCookie(string $name, $value = null, string $prefix = '')
{
if ($prefix === '' && $this->cookiePrefix !== '')
{
$prefix = $this->cookiePrefix;
}
$name = $prefix.$name;
foreach ($this->cookies as $cookie)
{
if ($cookie['name'] != $prefix.$name)
{
continue;
}
if ($value === null)
{
return true;
}
return $cookie['value'] == $value;
}
return false;
}
/**
* Returns the cookie
*
* @param string $name
* @param string $prefix
*
* @return mixed
*/
public function getCookie(string $name, string $prefix = '')
{
if ($prefix === '' && $this->cookiePrefix !== '')
{
$prefix = $this->cookiePrefix;
}
$name = $prefix.$name;
foreach ($this->cookies as $cookie)
{
if ($cookie['name'] == $name)
{
return $cookie;
}
}
}
/**
* Actually sets the cookies.
*/
protected function sendCookies()
{
if ($this->pretend)
{
return;
}
foreach ($this->cookies as $params)
{
setcookie(...$params);
}
}
/**
* Force a download.
*
@ -690,7 +944,7 @@ class Response extends Message implements ResponseInterface
}
elseif ($data === null)
{
if ( ! @is_file($filename) || ($filesize = @filesize($filename)) === false)
if (! @is_file($filename) || ($filesize = @filesize($filename)) === false)
{
return;
}
@ -707,7 +961,7 @@ class Response extends Message implements ResponseInterface
// Set the default MIME type to send
$mime = 'application/octet-stream';
$x = explode('.', $filename);
$x = explode('.', $filename);
$extension = end($x);
if ($setMime === true)
@ -729,10 +983,11 @@ class Response extends Message implements ResponseInterface
*
* Reference: http://digiblog.de/2011/04/19/android-and-the-download-file-headers/
*/
if (count($x) !== 1 && isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/Android\s(1|2\.[01])/', $_SERVER['HTTP_USER_AGENT']))
if (count($x) !== 1 && isset($_SERVER['HTTP_USER_AGENT'])
&& preg_match('/Android\s(1|2\.[01])/', $_SERVER['HTTP_USER_AGENT']))
{
$x[count($x) - 1] = strtoupper($extension);
$filename = implode('.', $x);
$x[count($x)-1] = strtoupper($extension);
$filename = implode('.', $x);
}
if ($data === null && ($fp = @fopen($filepath, 'rb')) === false)
@ -747,11 +1002,11 @@ class Response extends Message implements ResponseInterface
}
// Generate the server headers
header('Content-Type: ' . $mime);
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . $filesize);
header('Content-Length: '.$filesize);
header('Cache-Control: private, no-transform, no-store, must-revalidate');
// If we have raw data - just dump it
@ -761,7 +1016,7 @@ class Response extends Message implements ResponseInterface
}
// Flush 1MB chunks of data
while ( ! feof($fp) && ($data = fread($fp, 1048576)) !== false)
while (! feof($fp) && ($data = fread($fp, 1048576)) !== false)
{
echo $data;
}
@ -770,5 +1025,4 @@ class Response extends Message implements ResponseInterface
exit;
}
//--------------------------------------------------------------------
}

View File

@ -35,7 +35,6 @@
* @since Version 1.0.0
* @filesource
*/
defined('BASEPATH') || exit('No direct script access allowed');
/**
* CodeIgniter Directory Helpers

View File

@ -868,7 +868,7 @@ if ( ! function_exists('set_checkbox'))
}
// Unchecked checkbox and radio inputs are not even submitted by browsers ...
if ($_POST)
if (! empty($request->getPost()) || ! empty(old($field)))
{
return ($input === $value) ? ' checked="checked"' : '';
}
@ -925,7 +925,7 @@ if ( ! function_exists('set_radio'))
}
// Unchecked checkbox and radio inputs are not even submitted by browsers ...
if ($_POST)
if ($request->getPost())
{
return ($input === $value) ? ' checked="checked"' : '';
}

View File

@ -361,6 +361,8 @@ class Router implements RouterInterface
{
$routes = $this->collection->getRoutes($this->collection->getHTTPVerb());
$uri = ltrim($uri, '/ ');
// Don't waste any time
if (empty($routes))
{

View File

@ -152,6 +152,8 @@ class CIDatabaseTestCase extends CIUnitTestCase
*/
public function setUp()
{
parent::setUp();
$this->loadDependencies();
if ($this->refresh === true)

View File

@ -35,24 +35,51 @@
* @since Version 3.0.0
* @filesource
*/
use Config\Paths;
use CodeIgniter\Services;
use CodeIgniter\Events\Events;
use PHPUnit\Framework\TestCase;
use CodeIgniter\Log\TestLogger;
use Tests\Support\Log\TestLogger;
/**
* PHPunit test case.
*/
class CIUnitTestCase extends TestCase
{
use ReflectionHelper;
/**
* @var \CodeIgniter\CodeIgniter
*/
protected $app;
/**
* Path to Config folder, relative
* to the system folder.
* @var string
*/
protected $configPath = '../application/Config';
public function setUp()
{
parent::setUp();
if (! $this->app)
{
$this->app = $this->createApplication();
}
helper('url');
}
/**
* Custom function to hook into CodeIgniter's Logging mechanism
* to check if certain messages were logged during code execution.
*
* @param string $level
* @param null $expectedMessage
*
* @throws \Exception
*/
public function assertLogged(string $level, $expectedMessage = null)
{
@ -62,13 +89,14 @@ class CIUnitTestCase extends TestCase
return $result;
}
//--------------------------------------------------------------------
/**
* Hooks into CodeIgniter's Events system to check if a specific
* event was triggered or not.
*
* @param string $eventName
*
* @return bool
* @throws \Exception
*/
public function assertEventTriggered(string $eventName): bool
{
@ -87,5 +115,52 @@ class CIUnitTestCase extends TestCase
return $found;
}
//--------------------------------------------------------------------
/**
* Loads up an instance of CodeIgniter
* and gets the environment setup.
*
* @return mixed
*/
protected function createApplication()
{
$systemPath = realpath(__DIR__.'/../');
require_once $systemPath.'/'.$this->configPath.'/Paths.php';
$paths = $this->adjustPaths(new \Config\Paths());
$app = require $systemPath.'/bootstrap.php';
return $app;
}
/**
* Attempts to adjust our system paths to account
* for relative location of our tests folder.
* Not foolproof, but works well for default locations.
*
* @param \Config\Paths $paths
*
* @return \Config\Paths
*/
protected function adjustPaths(Paths $paths)
{
$tests = [
'systemDirectory', 'applicationDirectory', 'writableDirectory', 'testsDirectory'
];
foreach ($tests as $test)
{
if (is_dir($paths->$test) || strpos($paths->$test, '../') !== 0)
{
continue;
}
$check = substr($paths->$test, 3);
if (is_dir($check))
{
$paths->$test = $check;
}
}
return $paths;
}
}

View File

@ -0,0 +1,365 @@
<?php namespace CodeIgniter\Test;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\Response;
use PHPUnit\Framework\TestCase;
use Tests\Support\DOM\DOMParser;
class FeatureResponse extends TestCase
{
/**
* @var \CodeIgniter\HTTP\Response
*/
public $response;
/**
* @var \Tests\Support\DOM\DOMParser
*/
protected $domParser;
public function __construct(Response $response = null)
{
$this->response = $response;
if (is_string($this->response->getBody()))
{
$this->domParser = (new DOMParser())->withString($this->response->getBody());
}
}
//--------------------------------------------------------------------
// Simple Response Checks
//--------------------------------------------------------------------
/**
* Boils down the possible responses into a bolean valid/not-valid
* response type.
*
* @return bool
*/
public function isOK(): bool
{
// Only 200 and 300 range status codes
// are considered valid.
if ($this->response->getStatusCode() >= 400 || $this->response->getStatusCode() < 200)
{
return false;
}
// Empty bodies are not considered valid.
if (empty($this->response->getBody()))
{
return false;
}
return true;
}
/**
* Returns whether or not the Response was a redirect response
*
* @return bool
*/
public function isRedirect(): bool
{
return $this->response instanceof RedirectResponse;
}
/**
* Assert that the given response was a redirect.
*
* @throws \Exception
*/
public function assertRedirect()
{
$this->assertTrue($this->isRedirect(), "Response is not a RedirectResponse.");
}
/**
* Asserts that the status is a specific value.
*
* @param int $code
*
* @throws \Exception
*/
public function assertStatus(int $code)
{
$this->assertEquals($code, (int)$this->response->getStatusCode());
}
/**
* Asserts that the Response is considered OK.
*
* @throws \Exception
*/
public function assertOK()
{
$this->assertTrue($this->isOK(), "{$this->response->getStatusCode()} is not a successful status code, or the Response has an empty body.");
}
//--------------------------------------------------------------------
// Session Assertions
//--------------------------------------------------------------------
/**
* Asserts that an SESSION key has been set and, optionally, test it's value.
*
* @param string $key
* @param null $value
*
* @throws \Exception
*/
public function assertSessionHas(string $key, $value = null)
{
$this->assertTrue(array_key_exists($key, $_SESSION), "'{$key}' is not in the current \$_SESSION");
if ($value !== null)
{
$this->assertEquals($value, $_SESSION[$key], "The value of '{$key}' ({$value}) does not match expected value.");
}
}
/**
* Asserts the session is missing $key.
*
* @param string $key
*
* @throws \Exception
*/
public function assertSessionMissing(string $key)
{
$this->assertFalse(array_key_exists($key, $_SESSION), "'{$key}' should not be present in \$_SESSION.");
}
//--------------------------------------------------------------------
// Header Assertions
//--------------------------------------------------------------------
/**
* Asserts that the Response contains a specific header.
*
* @param string $key
* @param null $value
*
* @throws \Exception
*/
public function assertHeader(string $key, $value = null)
{
$this->assertTrue($this->response->hasHeader($key), "'{$key}' is not a valid Response header.");
if ($value !== null)
{
$this->assertEquals($value, $this->response->getHeaderLine($key), "The value of '{$key}' header ({$this->response->getHeaderLine($key)}) does not match expected value.");
}
}
/**
* Asserts the Response headers does not contain the specified header.
*
* @param string $key
*
* @throws \Exception
*/
public function assertHeaderMissing(string $key)
{
$this->assertFalse($this->response->hasHeader($key), "'{$key}' should not be in the Response headers.");
}
//--------------------------------------------------------------------
// Cookie Assertions
//--------------------------------------------------------------------
/**
* Asserts that the response has the specified cookie.
*
* @param string $key
* @param null $value
* @param string|null $prefix
*
* @throws \Exception
*/
public function assertCookie(string $key, $value = null, string $prefix = '')
{
$this->assertTrue($this->response->hasCookie($key, $value, $prefix), "No cookie found named '{$key}'.");
}
/**
* Assert the Response does not have the specified cookie set.
*
* @param string $key
* @param null $value
* @param string $prefix
*
* @throws \Exception
*/
public function assertCookieMissing(string $key)
{
$this->assertFalse($this->response->hasCookie($key), "Cookie named '{$key}' should not be set.");
}
/**
* Asserts that a cookie exists and has an expired time.
*
* @param string $key
* @param string $prefix
*
* @throws \Exception
*/
public function assertCookieExpired(string $key, string $prefix = '')
{
$this->assertTrue($this->response->hasCookie($key, null, $prefix));
$this->assertGreaterThan(time(), $this->response->getCookie($key, $prefix)['expires']);
}
//--------------------------------------------------------------------
// DomParser Assertions
//--------------------------------------------------------------------
/**
* Assert that the desired text can be found in the result body.
*
* @param string|null $search
* @param string|null $element
*
* @throws \Exception
*/
public function assertSee(string $search = null, string $element = null)
{
$this->assertTrue($this->domParser->see($search, $element), "Do not see '{$search}' in response.");
}
/**
* Asserts that we do not see the specified text.
*
* @param string|null $search
* @param string|null $element
*
* @throws \Exception
*/
public function assertDontSee(string $search = null, string $element = null)
{
$this->assertTrue($this->domParser->dontSee($search, $element), "I should not see '{$search}' in response.");
}
/**
* Assert that we see an element selected via a CSS selector.
*
* @param string $search
*
* @throws \Exception
*/
public function assertSeeElement(string $search)
{
$this->assertTrue($this->domParser->seeElement($search), "Do not see element with selector '{$search} in response.'");
}
/**
* Assert that we do not see an element selected via a CSS selector.
*
* @param string $search
*
* @throws \Exception
*/
public function assertDontSeeElement(string $search)
{
$this->assertTrue($this->domParser->dontSeeElement($search), "I should not see an element with selector '{$search}' in response.'");
}
/**
* Assert that we see a link with the matching text and/or class.
*
* @param string $text
* @param string|null $details
*
* @throws \Exception
*/
public function assertSeeLink(string $text, string $details=null)
{
$this->assertTrue($this->domParser->seeLink($text, $details), "Do no see anchor tag with the text {$text} in response.");
}
/**
* Assert that we see an input with name/value.
*
* @param string $field
* @param string|null $value
*
* @throws \Exception
*/
public function assertSeeInField(string $field, string $value=null)
{
$this->assertTrue($this->domParser->seeInField($field, $value), "Do no see input named {$field} with value {$value} in response.");
}
//--------------------------------------------------------------------
// JSON Methods
//--------------------------------------------------------------------
/**
* Returns the response's body as JSON
*
* @return mixed|string
*/
public function getJSON()
{
$response = $this->response->getJSON();
if (is_null($response))
{
$this->fail('The Response contained invalid JSON.');
}
return $response;
}
/**
*
*
* @param array $fragment
*
* @throws \Exception
*/
public function assertJSONFragment(array $fragment)
{
$json = json_decode($this->getJSON(), true);
$this->assertArraySubset($fragment, $json, false, "Response does not contain a matching JSON fragment.");
}
/**
* Asserts that the JSON exactly matches the passed in data.
* If the value being passed in is a string, it must be a json_encoded string.
*
* @param string|array $test
*
* @throws \Exception
*/
public function assertJSONExact($test)
{
$json = $this->getJSON();
if (is_array($test))
{
$config = new \Config\Format();
$formatter = $config->getFormatter('application/json');
$test = $formatter->format($test);
}
$this->assertJsonStringEqualsJsonString($test, $json, "Response does not contain matching JSON.");
}
//--------------------------------------------------------------------
// XML Methods
//--------------------------------------------------------------------
/**
* Returns the response' body as XML
*
* @return mixed|string
*/
public function getXML()
{
return $this->response->getXML();
}
}

View File

@ -0,0 +1,251 @@
<?php namespace CodeIgniter\Test;
use CodeIgniter\HTTP\URI;
use CodeIgniter\HTTP\Request;
use CodeIgniter\Events\Events;
use CodeIgniter\HTTP\UserAgent;
use CodeIgniter\HTTP\IncomingRequest;
/**
* Class FeatureTestCase
*
* Provides additional utilities for doing full HTTP testing
* against your application.
*
* @package CodeIgniter\Test
*/
class FeatureTestCase extends CIDatabaseTestCase
{
/**
* If present, will override application
* routes when using call().
* @var \CodeIgniter\Router\RouteCollection
*/
protected $routes;
/**
* Values to be set in the SESSION global
* before running the test.
* @var array
*/
protected $session = [];
/**
* Sets a RouteCollection that will override
* the application's route collection.
*
* @param array $routes
*
* @return $this
*/
protected function withRoutes(array $routes = null)
{
$collection = \Config\Services::routes();
if (count($routes))
{
foreach ($routes as $route)
{
$collection->{$route[0]}($route[1], $route[2]);
}
}
$this->routes = $collection;
return $this;
}
/**
* Sets any values that should exist during this session.
*
* @param array $values
*
* @return $this
*/
public function withSession(array $values)
{
$this->session = $values;
return $this;
}
/**
* Don't run any events while running this test.
*
* @return $this
*/
public function skipEvents()
{
Events::simulate(true);
return $this;
}
/**
* Calls a single URI, executes it, and returns a FeatureResponse
* instance that can be used to run many assertions against.
*
* @param string $method
* @param string $path
* @param array|null $params
*
* @return \CodeIgniter\Test\FeatureResponse
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function call(string $method, string $path, array $params = null)
{
// Simulate having a blank session
$_SESSION = [];
$request = $this->setupRequest($method, $path, $params);
$request = $this->populateGlobals($method, $request, $params);
$response = $this->app
->setRequest($request)
->run($this->routes, true);
$featureResponse = new FeatureResponse($response);
return $featureResponse;
}
/**
* Performs a GET request.
*
* @param string $path
* @param array|null $params
*
* @return \CodeIgniter\Test\FeatureResponse
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function get(string $path, array $params = null)
{
return $this->call('get', $path, $params);
}
/**
* Performs a POST request.
*
* @param string $path
* @param array|null $params
*
* @return \CodeIgniter\Test\FeatureResponse
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function post(string $path, array $params = null)
{
return $this->call('post', $path, $params);
}
/**
* Performs a PUT request
*
* @param string $path
* @param array|null $params
*
* @return \CodeIgniter\Test\FeatureResponse
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function put(string $path, array $params = null)
{
return $this->call('put', $path, $params);
}
/**
* Performss a PATCH request
*
* @param string $path
* @param array|null $params
*
* @return \CodeIgniter\Test\FeatureResponse
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function patch(string $path, array $params = null)
{
return $this->call('patch', $path, $params);
}
/**
* Performs a DELETE request.
*
* @param string $path
* @param array|null $params
*
* @return \CodeIgniter\Test\FeatureResponse
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function delete(string $path, array $params = null)
{
return $this->call('delete', $path, $params);
}
/**
* Performs an OPTIONS request.
*
* @param string $path
* @param array|null $params
*
* @return \CodeIgniter\Test\FeatureResponse
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function options(string $path, array $params = null)
{
return $this->call('delete', $path, $params);
}
/**
* Setup a Request object to use so that CodeIgniter
* won't try to auto-populate some of the items.
*
* @param string $method
* @param string|null $path
*
* @return \CodeIgniter\HTTP\IncomingRequest
*/
protected function setupRequest(string $method, string $path=null, $params = null)
{
$config = new \Config\App();
$uri = new URI($config->baseURL .'/'. trim($path, '/ '));
$request = new IncomingRequest($config, clone($uri), $params, new UserAgent());
$request->uri = $uri;
$request->setMethod($method);
$request->setProtocolVersion('1.1');
return $request;
}
/**
* Populates the data of our Request with "global" data
* relevant to the request, like $_POST data.
*
* Always populate the GET vars based on the URI.
*
* @param string $method
* @param \CodeIgniter\HTTP\Request $request
* @param array|null $params
*
* @return \CodeIgniter\HTTP\Request
*/
protected function populateGlobals(string $method, Request $request, array $params = null)
{
$request->setGlobal('get', $this->getPrivateProperty($request->uri, 'query'));
if ($method !== 'get')
{
$request->setGlobal($method, $params);
}
$_SESSION = $this->session;
return $request;
}
}

View File

@ -1,6 +1,4 @@
<?php
namespace Psr\Log;
<?php namespace Psr\Log;
/**
* Describes a logger instance

View File

@ -95,7 +95,11 @@ class Escaper
public function __construct($encoding = null)
{
if ($encoding !== null) {
$encoding = (string) $encoding;
if (! is_string($encoding)) {
throw new Exception\InvalidArgumentException(
get_class($this) . ' constructor parameter must be a string, received ' . gettype($encoding)
);
}
if ($encoding === '') {
throw new Exception\InvalidArgumentException(
get_class($this) . ' constructor parameter does not allow a blank value'
@ -103,7 +107,7 @@ class Escaper
}
$encoding = strtolower($encoding);
if (!in_array($encoding, $this->supportedEncodings)) {
if (! in_array($encoding, $this->supportedEncodings)) {
throw new Exception\InvalidArgumentException(
'Value of \'' . $encoding . '\' passed to ' . get_class($this)
. ' constructor parameter is invalid. Provide an encoding supported by htmlspecialchars()'
@ -321,7 +325,7 @@ class Escaper
$result = $this->convertEncoding($string, 'UTF-8', $this->getEncoding());
}
if (!$this->isUtf8($result)) {
if (! $this->isUtf8($result)) {
throw new Exception\RuntimeException(
sprintf('String to be escaped was not valid UTF-8 or could not be converted: %s', $result)
);

View File

@ -53,36 +53,51 @@ $pos = strrpos(FCPATH, $public.DIRECTORY_SEPARATOR);
/**
* The path to the main application directory. Just above public.
*/
define('ROOTPATH', substr_replace(FCPATH, '', $pos, strlen($public.DIRECTORY_SEPARATOR)));
if (! defined('ROOTPATH'))
{
define('ROOTPATH', substr_replace(FCPATH, '', $pos, strlen($public.DIRECTORY_SEPARATOR)));
}
/**
* The path to the application directory.
*/
define('APPPATH', realpath($paths->applicationDirectory).DIRECTORY_SEPARATOR);
if (! defined('APPPATH'))
{
define('APPPATH', realpath($paths->applicationDirectory).DIRECTORY_SEPARATOR);
}
/**
* The path to the system directory.
*/
define('BASEPATH', realpath($paths->systemDirectory).DIRECTORY_SEPARATOR);
if (! defined('BASEPATH'))
{
define('BASEPATH', realpath($paths->systemDirectory).DIRECTORY_SEPARATOR);
}
/**
* The path to the writable directory.
*/
define('WRITEPATH', realpath($paths->writableDirectory).DIRECTORY_SEPARATOR);
if (! defined('WRITEPATH'))
{
define('WRITEPATH', realpath($paths->writableDirectory).DIRECTORY_SEPARATOR);
}
/**
* The path to the tests directory
*/
define('TESTPATH', realpath($paths->testsDirectory).DIRECTORY_SEPARATOR);
if (! defined('TESTPATH'))
{
define('TESTPATH', realpath($paths->testsDirectory).DIRECTORY_SEPARATOR);
}
/*
* ---------------------------------------------------------------
* GRAB OUR CONSTANTS & COMMON
* ---------------------------------------------------------------
*/
require APPPATH.'Config/Constants.php';
require_once APPPATH.'Config/Constants.php';
require BASEPATH.'Common.php';
require_once BASEPATH.'Common.php';
/*
* ---------------------------------------------------------------
@ -94,12 +109,15 @@ require BASEPATH.'Common.php';
* that the config files can use the path constants.
*/
require BASEPATH.'Autoloader/Autoloader.php';
require APPPATH .'Config/Autoload.php';
require APPPATH .'Config/Services.php';
require_once BASEPATH.'Autoloader/Autoloader.php';
require_once APPPATH .'Config/Autoload.php';
require_once APPPATH .'Config/Services.php';
// Use Config\Services as CodeIgniter\Services
class_alias('Config\Services', 'CodeIgniter\Services');
if (! class_exists('CodeIgniter\Services', false))
{
class_alias('Config\Services', 'CodeIgniter\Services');
}
$loader = CodeIgniter\Services::autoloader();
$loader->initialize(new Config\Autoload());
@ -108,12 +126,12 @@ $loader->register(); // Register the loader with the SPL autoloader stack.
// Now load Composer's if it's available
if (file_exists(COMPOSER_PATH))
{
require COMPOSER_PATH;
require_once COMPOSER_PATH;
}
// Load environment settings from .env files
// into $_SERVER and $_ENV
require BASEPATH . 'Config/DotEnv.php';
require_once BASEPATH . 'Config/DotEnv.php';
$env = new \CodeIgniter\Config\DotEnv(ROOTPATH);
$env->load();

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Autoloader;
<?php namespace Tests\Support\Autoloader;
use CodeIgniter\Autoloader\Autoloader;
class MockAutoloader extends Autoloader
{

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Autoloader;
<?php namespace Tests\Support\Autoloader;
use CodeIgniter\Autoloader\FileLocator;
class MockFileLocator extends FileLocator
{

View File

@ -1,4 +1,4 @@
<?php namespace CodeIgniter\Cache\Handlers;
<?php namespace Tests\Support\Cache\Handlers;
use CodeIgniter\Cache\CacheInterface;

View File

@ -1,4 +1,4 @@
<?php namespace Config;
<?php namespace Tests\Support\Config;
class MockAppConfig
{

View File

@ -1,4 +1,6 @@
<?php namespace Config;
<?php namespace Tests\Support\Config;
use Config\Autoload;
class MockAutoload extends Autoload
{

View File

@ -1,4 +1,4 @@
<?php namespace Config;
<?php namespace Tests\Support\Config;
class MockCLIConfig extends \Config\App
{

View File

@ -1,5 +1,4 @@
<?php namespace Config;
<?php namespace Tests\Support\Config;
class MockLogger
{
@ -85,7 +84,7 @@ class MockLogger
// File Handler
//--------------------------------------------------------------------
'CodeIgniter\Log\Handlers\TestHandler' => [
'Tests\Support\Log\Handlers\TestHandler' => [
/*
* The log levels that this handler will handle.

View File

@ -1,4 +1,7 @@
<?php namespace CodeIgniter\Database;
<?php namespace Tests\Support\Database;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\ConnectionInterface;
class MockBuilder extends BaseBuilder {

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Database;
<?php namespace Tests\Support\Database;
use CodeIgniter\Database\BaseConnection;
class MockConnection extends BaseConnection
{

View File

@ -1,6 +1,8 @@
<?php namespace CodeIgniter\Database;
<?php namespace Tests\Support\Database;
use CodeIgniter\Database\Query;
class MockQuery extends Query
{
}

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Database;
<?php namespace Tests\Support\Database;
use CodeIgniter\Database\BaseResult;
class MockResult extends BaseResult
{
@ -9,7 +11,7 @@ class MockResult extends BaseResult
*/
public function getFieldCount(): int
{
}
//--------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
<?php namespace CodeIgniter\Events;
<?php namespace Tests\Support\Events;
/**
* CodeIgniter
@ -36,6 +36,8 @@
* @filesource
*/
use CodeIgniter\Events\Events;
/**
* Events
*/

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\HTTP;
<?php namespace Tests\Support\HTTP;
use CodeIgniter\HTTP\CURLRequest;
/**
* Class MockCURLRequest

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\HTTP;
<?php namespace Tests\Support\HTTP;
use CodeIgniter\HTTP\IncomingRequest;
class MockIncomingRequest extends IncomingRequest
{

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\HTTP;
<?php namespace Tests\Support\HTTP;
use CodeIgniter\HTTP\Response;
/**
* Class MockResponse
@ -21,13 +23,13 @@ class MockResponse extends Response
foreach
(
[
'value',
'expire',
'domain',
'path',
'prefix',
'secure',
'httponly',
'value',
'expire',
'domain',
'path',
'prefix',
'secure',
'httponly',
'name'
] as $item
)
@ -43,16 +45,16 @@ class MockResponse extends Response
$_COOKIE[$prefix . $name] = $value;
/*
TODO: Find a way to use setcookie()
TODO: Find a way to use setcookie()
without it throwing header issues.
setcookie
(
$prefix.$name,
$value,
$expire,
$path,
$domain,
$secure,
$prefix.$name,
$value,
$expire,
$path,
$domain,
$secure,
$httponly
);
*/
@ -60,7 +62,7 @@ class MockResponse extends Response
//--------------------------------------------------------------------
public function hasCookie(string $name): bool
public function hasCookie(string $name, $value = null, string $prefix = ''): bool
{
return array_key_exists($name, $_COOKIE);
}
@ -69,15 +71,15 @@ class MockResponse extends Response
public function deleteCookie
(
$name,
string $domain = '',
string $path = '/',
$name,
string $domain = '',
string $path = '/',
string $prefix = ''
)
{
$COOKIE[$name] = null;
unset($COOKIE[$name]);
//set_cookie($name, '', '', $domain, $path, $prefix);
}

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Language;
<?php namespace Tests\Support\Language;
use CodeIgniter\Language\Language;
class MockLanguage extends Language
{

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Language;
<?php namespace Tests\Support\Language;
use CodeIgniter\Language\Language;
class SecondMockLanguage extends Language
{

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Log\Handlers;
<?php namespace Tests\Support\Log\Handlers;
use CodeIgniter\Log\Handlers\HandlerInterface;
/**
* Class TestHandler
@ -96,4 +98,4 @@ class TestHandler implements HandlerInterface
//--------------------------------------------------------------------
}
}

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Log;
<?php namespace Tests\Support\Log;
use CodeIgniter\Log\Logger;
class TestLogger extends Logger
{

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter;
<?php namespace Tests\Support;
use CodeIgniter\CodeIgniter;
class MockCodeIgniter extends CodeIgniter
{

View File

@ -1,5 +1,6 @@
<?php namespace CodeIgniter\Security;
<?php namespace Tests\Support\Security;
use CodeIgniter\Security\Security;
use CodeIgniter\HTTP\RequestInterface;
class MockSecurity extends Security

View File

@ -1,4 +1,6 @@
<?php namespace CodeIgniter\Session;
<?php namespace Tests\Support\Session;
use CodeIgniter\Session\Session;
/**
* Class MockSession

View File

@ -1,4 +1,4 @@
<?php namespace CodeIgniter\Validation;
<?php namespace Tests\Support\Validation;
class TestRules {

View File

@ -5,114 +5,24 @@ ini_set('display_startup_errors', '1');
// Make sure it recognizes that we're testing.
$_SERVER['CI_ENVIRONMENT'] = 'testing';
// Get our system paths
require 'application/Config/Paths.php';
$paths = new \Config\Paths();
define('ENVIRONMENT', 'testing');
// Path to the front controller (this file)
define('FCPATH', getcwd().'/public'.DIRECTORY_SEPARATOR);
/*
* ---------------------------------------------------------------
* SETUP OUR PATH CONSTANTS
* ---------------------------------------------------------------
*
* The path constants provide convenient access to the folders
* throughout the application. We have to setup them up here
* so they are available in the config files that are loaded.
*/
// Path to code root folder (just up from public)
$pos = strrpos(FCPATH, 'public'.DIRECTORY_SEPARATOR);
define('ROOTPATH', substr_replace(FCPATH, '', $pos, strlen('public'.DIRECTORY_SEPARATOR)));
// The path to the "application" folder
define('APPPATH', realpath(FCPATH.$paths->applicationDirectory).DIRECTORY_SEPARATOR);
// Path to the system folder
define('BASEPATH', realpath(FCPATH.$paths->systemDirectory).DIRECTORY_SEPARATOR);
// Path to the writable directory.
define('WRITEPATH', realpath(FCPATH.$paths->writableDirectory).DIRECTORY_SEPARATOR);
// The path to the "tests" directory
define('TESTPATH', realpath(FCPATH.$paths->testsDirectory).DIRECTORY_SEPARATOR);
define('TESTPATH', realpath(__DIR__.'/../').'/');
define('SUPPORTPATH', realpath(TESTPATH.'_support/').'/');
// Use special Services for testing. These allow
// insert mocks in place of normal services.
include BASEPATH.'Config/Services.php';
/*
* ---------------------------------------------------------------
* GRAB OUR CONSTANTS & COMMON
* ---------------------------------------------------------------
*/
require APPPATH.'Config/Constants.php';
// Use special global functions for testing.
require_once SUPPORTPATH.'MockCommon.php';
require BASEPATH.'Common.php';
/*
* ---------------------------------------------------------------
* LOAD OUR AUTOLOADER
* ---------------------------------------------------------------
*
* The autoloader allows all of the pieces to work together
* in the framework. We have to load it here, though, so
* that the config files can use the path constants.
*/
require BASEPATH.'Autoloader/Autoloader.php';
require APPPATH .'Config/Autoload.php';
require APPPATH .'Config/Services.php';
$loader = CodeIgniter\Config\Services::autoloader();
$loader->initialize(new Config\Autoload());
$loader->register(); // Register the loader with the SPL autoloader stack.
// Add namespace paths to autoload mocks for testing.
$loader->addNamespace('CodeIgniter', SUPPORTPATH);
$loader->addNamespace('Config', SUPPORTPATH.'Config');
$loader->addNamespace('Tests\Support', SUPPORTPATH);
// Now load Composer's if it's available
if (file_exists(COMPOSER_PATH))
{
require COMPOSER_PATH;
}
// Load environment settings from .env files
// into $_SERVER and $_ENV
require BASEPATH . 'Config/DotEnv.php';
$env = new \CodeIgniter\Config\DotEnv(ROOTPATH);
$env->load();
// Set environment values that would otherwise stop the framework from functioning during tests.
if (! isset($_SERVER['app.baseURL']))
{
$_SERVER['app.baseURL'] = 'http://example.com';
}
/*
* ---------------------------------------------------------------
* GRAB OUR CODEIGNITER INSTANCE
* ---------------------------------------------------------------
*
* The CodeIgniter class contains the core functionality to make
* the application run, and does all of the dirty work to get
* the pieces all working together.
*/
$app = new \CodeIgniter\CodeIgniter(new \Config\App());
$app->initialize();
//--------------------------------------------------------------------
// Load our TestCase
//--------------------------------------------------------------------
require TESTPATH.'_support/CIUnitTestCase.php';
require __DIR__.'/CIUnitTestCase.php';

View File

@ -0,0 +1,14 @@
<?php
use CodeIgniter\Test\FeatureTestCase;
class HomeTest extends FeatureTestCase
{
public function testCanLoadPage()
{
$response = $this->call('post', site_url().'?foo=bar&bar=baz', ['xxx' => 'yyy']);
$this->assertInstanceOf(\CodeIgniter\Test\FeatureResponse::class, $response);
}
}

View File

@ -1,16 +1,14 @@
<?php namespace CodeIgniter\API;
use CodeIgniter\Controller;
use CodeIgniter\Format\JSONFormatter;
use CodeIgniter\Format\XMLFormatter;
use CodeIgniter\HTTP\MockIncomingRequest;
use CodeIgniter\HTTP\MockResponse;
use CodeIgniter\HTTP\URI;
use CodeIgniter\HTTP\UserAgent;
use Tests\Support\HTTP\MockResponse;
use CodeIgniter\Format\XMLFormatter;
use CodeIgniter\Format\JSONFormatter;
use Tests\Support\HTTP\MockIncomingRequest;
class ResponseTraitTest extends \CIUnitTestCase
{
protected $request;
protected $response;
@ -45,8 +43,11 @@ class ResponseTraitTest extends \CIUnitTestCase
$config = array_merge($config, $userConfig);
$this->request = new MockIncomingRequest((object) $config, new URI($uri), null, new UserAgent());
$this->response = new MockResponse((object) $config);
if (is_null($this->request))
{
$this->request = new MockIncomingRequest((object)$config, new URI($uri), null, new UserAgent());
$this->response = new MockResponse((object)$config);
}
// Insert headers into request.
$headers = [
@ -82,7 +83,31 @@ class ResponseTraitTest extends \CIUnitTestCase
return $controller;
}
//--------------------------------------------------------------------
public function testNoFormatterJSON()
{
$this->formatter = null;
$controller = $this->makeController([], 'http://codeigniter.com', ['Accept' => 'application/json']);
$controller->respondCreated(['id' => 3], 'A Custom Reason');
$this->assertEquals('A Custom Reason', $this->response->getReason());
$this->assertEquals(201, $this->response->getStatusCode());
$expected = <<<EOH
{
"id": 3
}
EOH;
$this->assertEquals($expected, $this->response->getBody());
}
public function testNoFormatterHTML()
{
$this->formatter = null;
$controller = $this->makeController();
$controller->respondCreated('A Custom Reason');
$this->assertEquals('A Custom Reason', $this->response->getBody());
}
public function testRespondSets404WithNoData()
{
@ -93,8 +118,6 @@ class ResponseTraitTest extends \CIUnitTestCase
$this->assertNull($this->response->getBody());
}
//--------------------------------------------------------------------
public function testRespondSetsStatusWithEmptyData()
{
$controller = $this->makeController();
@ -104,8 +127,6 @@ class ResponseTraitTest extends \CIUnitTestCase
$this->assertNull($this->response->getBody());
}
//--------------------------------------------------------------------
public function testRespondSetsCorrectBodyAndStatus()
{
$controller = $this->makeController();
@ -117,8 +138,6 @@ class ResponseTraitTest extends \CIUnitTestCase
$this->assertEquals('Created', $this->response->getReason());
}
//--------------------------------------------------------------------
public function testRespondWithCustomReason()
{
$controller = $this->makeController();
@ -339,25 +358,6 @@ class ResponseTraitTest extends \CIUnitTestCase
$this->tryValidContentType($goodMimes[$i], $goodMimes[$i] . $chars);
}
private function tryValidResponse($mimeType, $contentType)
{
$original = $_SERVER;
$_SERVER['CONTENT_TYPE'] = $mimeType;
$controller = $this->makeController([], 'http://codeigniter.com', ['Accept' => $mimeType]);
$this->assertEquals($mimeType, $this->request->getHeaderLine('Accept'), 'Request header...');
$this->assertEquals($contentType, $this->response->getHeaderLine('Content-Type'), 'Response header pre-response...');
$this->response->setContentType($contentType);
$controller->respond('HTML assumed');
$this->assertEquals(200, $this->response->getStatusCode());
$expected = 'HTML assumed';
$this->assertEquals($expected, $this->response->getBody());
$_SERVER = $original;
}
public function testXMLFormatter()
{
$this->formatter = new XMLFormatter();
@ -370,32 +370,6 @@ class ResponseTraitTest extends \CIUnitTestCase
<?xml version="1.0"?>
<response><id>3</id></response>
EOH;
$this->assertEquals($expected, $this->response->getBody());
}
public function testNoFormatterHTML()
{
$this->formatter = null;
$controller = $this->makeController();
$controller->respondCreated('A Custom Reason');
$this->assertEquals('A Custom Reason', $this->response->getBody());
}
public function testNoFormatterJSON()
{
$this->formatter = null;
$controller = $this->makeController([], 'http://codeigniter.com', ['Accept' => 'application/json']);
$controller->respondCreated(['id' => 3], 'A Custom Reason');
$this->assertEquals('A Custom Reason', $this->response->getReason());
$this->assertEquals(201, $this->response->getStatusCode());
$expected = <<<EOH
{
"id": 3
}
EOH;
$this->assertEquals($expected, $this->response->getBody());
}

View File

@ -1,6 +1,7 @@
<?php namespace CodeIgniter\Autoloader;
use Config\Autoload;
use Tests\Support\Autoloader\MockAutoloader;
//--------------------------------------------------------------------
@ -11,8 +12,10 @@ class AutoloaderTest extends \CIUnitTestCase
//--------------------------------------------------------------------
protected function setUp()
public function setUp()
{
parent::setUp();
$config = new Autoload();
$config->classmap = [

View File

@ -1,6 +1,7 @@
<?php namespace CodeIgniter\Autoloader;
use Config\MockAutoload;
use Tests\Support\Config\MockAutoload;
use Tests\Support\Autoloader\MockFileLocator;
class FileLocatorTest extends \CIUnitTestCase
{
@ -14,12 +15,15 @@ class FileLocatorTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$config = new MockAutoload();
$config->psr4 = [
'App\Libraries' => '/application/somewhere',
'App' => '/application',
'Sys' => BASEPATH,
'Blog' => '/modules/blog'
'Blog' => '/modules/blog',
'Tests/Support' => TESTPATH.'_support/',
];
$this->loader = new MockFileLocator($config);

View File

@ -9,6 +9,8 @@ class CLITest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
CITestStreamFilter::$buffer = '';
$this->stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter');
}

View File

@ -1,7 +1,7 @@
<?php namespace CodeIgniter\CLI;
use Config\MockCLIConfig;
use CodeIgniter\HTTP\UserAgent;
use Tests\Support\Config\MockCLIConfig;
use CodeIgniter\Test\Filters\CITestStreamFilter;
class CommandRunnerTest extends \CIUnitTestCase
@ -11,6 +11,8 @@ class CommandRunnerTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
CITestStreamFilter::$buffer = '';
$this->stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter');

View File

@ -1,6 +1,7 @@
<?php namespace CodeIgniter\CLI;
use Config\MockCLIConfig;
use Tests\Support\MockCodeIgniter;
use Tests\Support\Config\MockCLIConfig;
use CodeIgniter\Test\Filters\CITestStreamFilter;
class ConsoleTest extends \CIUnitTestCase
@ -10,6 +11,8 @@ class ConsoleTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
CITestStreamFilter::$buffer = '';
$this->stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter');
@ -25,9 +28,8 @@ class ConsoleTest extends \CIUnitTestCase
$_SERVER['argv'] = ['spark', 'list'];
$_SERVER['argc'] = 2;
CLI::init();
$this->app = new \CodeIgniter\MockCodeIgniter(new MockCLIConfig());
// $this->app->initialize();
$this->app = new MockCodeIgniter(new MockCLIConfig());
}
public function tearDown()

View File

@ -8,6 +8,8 @@ class CacheFactoryTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->cacheFactory = new CacheFactory();
//Initialize path

View File

@ -26,6 +26,8 @@ class FileHandlerTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
//Initialize path
$this->config = new \Config\Cache();
$this->config->storePath .= self::$directory;

View File

@ -18,6 +18,8 @@ class MemcachedHandlerTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->config = new \Config\Cache();
$this->memcachedHandler = new MemcachedHandler($this->config->memcached);

View File

@ -53,6 +53,8 @@ class RedisHandlerTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->config = new \Config\Cache();
$this->redisHandler = new RedisHandler($this->config->redis);

View File

@ -1,8 +1,9 @@
<?php namespace CodeIgniter;
use CodeIgniter\Autoloader\MockFileLocator;
use CodeIgniter\Router\RouteCollection;
use Config\App;
use Tests\Support\MockCodeIgniter;
use CodeIgniter\Router\RouteCollection;
use Tests\Support\Autoloader\MockFileLocator;
/**
* @backupGlobals enabled
@ -20,6 +21,8 @@ class CodeIgniterTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
Services::reset();
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';

View File

@ -10,6 +10,8 @@ class CommomFunctionsTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
unset($_ENV['foo'], $_SERVER['foo']);
}
@ -70,7 +72,7 @@ class CommomFunctionsTest extends \CIUnitTestCase
$_SERVER['REQUEST_METHOD'] = 'GET';
$response = $this->createMock(\CodeIgniter\HTTP\Response::class);
$routes = new \CodeIgniter\Router\RouteCollection(new \CodeIgniter\Autoloader\MockFileLocator(new \Config\Autoload()));
$routes = new \CodeIgniter\Router\RouteCollection(new \Tests\Support\Autoloader\MockFileLocator(new \Config\Autoload()));
\CodeIgniter\Services::injectMock('response', $response);
\CodeIgniter\Services::injectMock('routes', $routes);

View File

@ -11,6 +11,8 @@ class BaseConfigTest extends CIUnitTestCase
public function setup()
{
parent::setUp();
$this->fixturesFolder = __DIR__ . '/fixtures';
if ( ! class_exists('SimpleConfig', false))

View File

@ -14,6 +14,8 @@ class DotEnvTest extends \CIUnitTestCase
public function setup()
{
parent::setUp();
$this->fixturesFolder = __DIR__.'/fixtures';
$file = "unreadable.env";
$path = rtrim($this->fixturesFolder, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file;

View File

@ -8,6 +8,8 @@ class ServicesTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->original = $_SERVER;
// $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'es; q=1.0, en; q=0.5';
$this->config = new App();

View File

@ -1,7 +1,8 @@
<?php namespace CodeIgniter;
use CodeIgniter\HTTP\UserAgent;
use Config\App;
use CodeIgniter\HTTP\UserAgent;
use Tests\Support\MockCodeIgniter;
/**
* Exercise our core Controller class.
@ -39,7 +40,7 @@ class ControllerTest extends \CIUnitTestCase
public function setUp()
{
Services::reset();
parent::setUp();
$this->config = new App();
$this->request = new \CodeIgniter\HTTP\IncomingRequest($this->config, new \CodeIgniter\HTTP\URI('https://somwhere.com'), null, new UserAgent());

View File

@ -1,6 +1,8 @@
<?php namespace CodeIgniter\Database;
use Tests\Support\Database\MockConnection;
class BaseConnectionTest extends \CIUnitTestCase
{
protected $options = [

View File

@ -1,14 +1,17 @@
<?php namespace CodeIgniter\Database;
use Tests\Support\Database\MockConnection;
class QueryTest extends \CIUnitTestCase
{
protected $db;
//--------------------------------------------------------------------
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,6 +1,6 @@
<?php namespace Builder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class AliasTest extends \CIUnitTestCase
{
@ -10,6 +10,8 @@ class AliasTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class CountTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class CountTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,6 +1,6 @@
<?php namespace Builder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class DeleteTest extends \CIUnitTestCase
{
@ -10,6 +10,8 @@ class DeleteTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class DistinctTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class DistinctTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class EmptyTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class EmptyTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class FromTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class FromTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class GroupTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class GroupTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\Query;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class InsertTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class InsertTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class JoinTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class JoinTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class LikeTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class LikeTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class LimitTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class LimitTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class OrderTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class OrderTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,6 +1,6 @@
<?php namespace CodeIgniter\Database\Builder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class PrefixTest extends \CIUnitTestCase
{
@ -10,6 +10,8 @@ class PrefixTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection(['DBPrefix' => 'ci_']);
}

View File

@ -1,6 +1,6 @@
<?php namespace Builder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class ReplaceTest extends \CIUnitTestCase
{
@ -10,6 +10,8 @@ class ReplaceTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace CodeIgniter\Database\Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class SelectTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class SelectTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,7 +1,7 @@
<?php namespace Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class TruncateTest extends \CIUnitTestCase
{
@ -11,6 +11,8 @@ class TruncateTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,8 +1,8 @@
<?php namespace CodeIgniter\Database\Builder;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\MockConnection;
use CodeIgniter\Database\MockQuery;
use Tests\Support\Database\MockQuery;
use Tests\Support\Database\MockConnection;
class UpdateTest extends \CIUnitTestCase
{
@ -12,6 +12,8 @@ class UpdateTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,6 +1,6 @@
<?php namespace Builder;
use CodeIgniter\Database\MockConnection;
use Tests\Support\Database\MockConnection;
class WhereTest extends \CIUnitTestCase
{
@ -10,6 +10,8 @@ class WhereTest extends \CIUnitTestCase
public function setUp()
{
parent::setUp();
$this->db = new MockConnection([]);
}

View File

@ -1,6 +1,8 @@
<?php namespace CodeIgniter\Database\Live;
class AliasTest extends \CIDatabaseTestCase
use CodeIgniter\Test\CIDatabaseTestCase;
class AliasTest extends CIDatabaseTestCase
{
protected $refresh = true;

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class CIDbTestCaseTest extends \CIDatabaseTestCase
class CIDbTestCaseTest extends CIDatabaseTestCase
{
protected $refresh = true;
@ -15,7 +17,7 @@ class CIDbTestCaseTest extends \CIDatabaseTestCase
$this->seeInDatabase('user', ['name' => 'Ricky', 'email' => 'sofine@example.com', 'country' => 'US']);
}
//--------------------------------------------------------------------
public function testDontSeeInDatabase()
@ -43,5 +45,5 @@ class CIDbTestCaseTest extends \CIDatabaseTestCase
//--------------------------------------------------------------------
}
}

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class CountTest extends \CIDatabaseTestCase
class CountTest extends CIDatabaseTestCase
{
protected $refresh = true;
@ -46,4 +48,4 @@ class CountTest extends \CIDatabaseTestCase
}
//--------------------------------------------------------------------
}
}

View File

@ -1,11 +1,12 @@
<?php namespace CodeIgniter\Database\Live;
use \CodeIgniter\Database\Exceptions\DatabaseException;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class DeleteTest extends \CIDatabaseTestCase
class DeleteTest extends CIDatabaseTestCase
{
protected $refresh = true;

View File

@ -1,21 +1,23 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class EmptyTest extends \CIDatabaseTestCase
class EmptyTest extends CIDatabaseTestCase
{
protected $refresh = true;
protected $seed = 'CITestSeeder';
public function testEmpty()
public function testEmpty()
{
$this->db->table('misc')->emptyTable();
$this->assertEquals(0, $this->db->table('misc')->countAll());
}
//--------------------------------------------------------------------
public function testTruncate()
@ -26,4 +28,4 @@ class EmptyTest extends \CIDatabaseTestCase
}
//--------------------------------------------------------------------
}
}

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class ForgeTest extends \CIDatabaseTestCase
class ForgeTest extends CIDatabaseTestCase
{
protected $refresh = true;

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class FromTest extends \CIDatabaseTestCase
class FromTest extends CIDatabaseTestCase
{
protected $refresh = true;

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class GetTest extends \CIDatabaseTestCase
class GetTest extends CIDatabaseTestCase
{
protected $refresh = true;
@ -61,4 +63,4 @@ class GetTest extends \CIDatabaseTestCase
}
//--------------------------------------------------------------------
}
}

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class GroupTest extends \CIDatabaseTestCase
class GroupTest extends CIDatabaseTestCase
{
protected $refresh = true;

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class IncrementTest extends \CIDatabaseTestCase
class IncrementTest extends CIDatabaseTestCase
{
protected $refresh = true;
@ -60,4 +62,4 @@ class IncrementTest extends \CIDatabaseTestCase
}
//--------------------------------------------------------------------
}
}

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class InsertTest extends \CIDatabaseTestCase
class InsertTest extends CIDatabaseTestCase
{
protected $refresh = true;

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class JoinTest extends \CIDatabaseTestCase
class JoinTest extends CIDatabaseTestCase
{
protected $refresh = true;
@ -26,4 +28,4 @@ class JoinTest extends \CIDatabaseTestCase
//--------------------------------------------------------------------
}
}

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class LikeTest extends \CIDatabaseTestCase
class LikeTest extends CIDatabaseTestCase
{
protected $refresh = true;

View File

@ -1,9 +1,11 @@
<?php namespace CodeIgniter\Database\Live;
use CodeIgniter\Test\CIDatabaseTestCase;
/**
* @group DatabaseLive
*/
class LimitTest extends \CIDatabaseTestCase
class LimitTest extends CIDatabaseTestCase
{
protected $refresh = true;

View File

@ -2,6 +2,7 @@
use CodeIgniter\I18n\Time;
use CodeIgniter\Model;
use CodeIgniter\Test\CIDatabaseTestCase;
use CodeIgniter\Test\ReflectionHelper;
use Tests\Support\Models\EntityModel;
use Tests\Support\Models\EventModel;
@ -13,7 +14,7 @@ use Tests\Support\Models\ValidModel;
/**
* @group DatabaseLive
*/
class ModelTest extends \CIDatabaseTestCase
class ModelTest extends CIDatabaseTestCase
{
use ReflectionHelper;

Some files were not shown because too many files have changed in this diff Show More