diff --git a/.gitignore b/.gitignore index 435185857a..32c14d01b5 100644 --- a/.gitignore +++ b/.gitignore @@ -63,6 +63,8 @@ writable/uploads/* writable/debugbar/* +application/Database/Migrations/2* + php_errors.log #------------------------- @@ -124,4 +126,4 @@ nb-configuration.xml .vscode/ /results/ -/phpunit.xml \ No newline at end of file +/phpunit.xml diff --git a/.travis.yml b/.travis.yml index 4c01894e82..b724db7167 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ php: matrix: fast_finish: true allow_failures: - - php: 7.2 - php: nightly global: diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d720c67e40..608abb0fbf 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,14 +20,14 @@ ./system - ./system/bootstrap.php - ./system/Commands/Sessions/Views/migration.tpl.php - ./system/ComposerScripts.php - ./system/Config/Routes.php ./system/Debug/Toolbar/Views ./system/Pager/Views ./system/ThirdParty ./system/Validation/Views + ./system/bootstrap.php + ./system/Commands/Sessions/Views/migration.tpl.php + ./system/ComposerScripts.php + ./system/Config/Routes.php diff --git a/system/Commands/Server/Serve.php b/system/Commands/Server/Serve.php index e101c9e5fb..849abef0fd 100644 --- a/system/Commands/Server/Serve.php +++ b/system/Commands/Server/Serve.php @@ -1,25 +1,68 @@ 'The PHP Binary [default: "PHP_BINARY"]', - '-host' => 'The HTTP Host [default: "localhost"]', - '-port' => 'The HTTP Host Port [default: "8080"]', + protected $usage = 'serve'; + protected $arguments = []; + protected $options = [ + '-php' => 'The PHP Binary [default: "PHP_BINARY"]', + '-host' => 'The HTTP Host [default: "localhost"]', + '-port' => 'The HTTP Host Port [default: "8080"]', ]; public function run(array $params) { // Collect any user-supplied options and apply them - $php = CLI::getOption('php') ?? PHP_BINARY; + $php = CLI::getOption('php') ?? PHP_BINARY; $host = CLI::getOption('host') ?? 'localhost'; $port = CLI::getOption('port') ?? '8080'; @@ -38,4 +81,5 @@ class Serve extends BaseCommand // to ensure our environment is set and it simulates basic mod_rewrite. passthru("{$php} -S {$host}:{$port} -t {$docroot} {$rewrite}"); } + } diff --git a/system/Commands/Server/rewrite.php b/system/Commands/Server/rewrite.php index ca2a061f84..a7af4d4211 100644 --- a/system/Commands/Server/rewrite.php +++ b/system/Commands/Server/rewrite.php @@ -6,8 +6,9 @@ * development server based around PHP's built-in development * server. This file simply tries to mimic Apache's mod_rewrite * functionality so the site will operate as normal. + * */ - +// @codeCoverageIgnoreStart // Avoid this file run when listing commands if (php_sapi_name() === 'cli') { @@ -36,3 +37,4 @@ if ($uri !== '/' && (is_file($path) || is_dir($path))) // Otherwise, we'll load the index file and let // the framework handle the request from here. require_once $fcpath . 'index.php'; +// @codeCoverageIgnoreEnd diff --git a/system/Commands/Sessions/CreateMigration.php b/system/Commands/Sessions/CreateMigration.php index 18551acc5b..5c9427e067 100644 --- a/system/Commands/Sessions/CreateMigration.php +++ b/system/Commands/Sessions/CreateMigration.php @@ -39,6 +39,12 @@ use CodeIgniter\CLI\BaseCommand; use CodeIgniter\CLI\CLI; use Config\App; +/** + * Creates a migration file for database sessions. + * + * @package CodeIgniter\Commands + */ + class CreateMigration extends BaseCommand { @@ -98,7 +104,7 @@ class CreateMigration extends BaseCommand { $config = new App(); - $tableName = CLI::getOption('t') ?? $config->sessionSavePath ?? 'ci_sessions'; + $tableName = CLI::getOption('t') ?? 'ci_sessions'; $path = APPPATH . 'Database/Migrations/' . date('YmdHis_') . 'create_' . $tableName . '_table' . '.php'; diff --git a/system/Common.php b/system/Common.php index 48bb5bddbe..61380b9ff7 100644 --- a/system/Common.php +++ b/system/Common.php @@ -440,8 +440,10 @@ if ( ! function_exists('log_message')) return $logger->log($level, $message, $context); } + // @codeCoverageIgnoreStart return Services::logger(true) ->log($level, $message, $context); + // @codeCoverageIgnoreEnd } } @@ -668,6 +670,9 @@ if ( ! function_exists('force_https')) * Defaults to 1 year. * @param RequestInterface $request * @param ResponseInterface $response + * + * Not testable, as it will exit! + * @codeCoverageIgnore */ function force_https(int $duration = 31536000, RequestInterface $request = null, ResponseInterface $response = null) { @@ -837,6 +842,8 @@ if ( ! function_exists('is_really_writable')) * @param string $file * * @return bool + * + * @codeCoverageIgnore Not practical to test, as travis runs on linux */ function is_really_writable($file) { @@ -931,6 +938,8 @@ if ( ! function_exists('function_usable')) * @param string $function_name Function to check for * @return bool TRUE if the function exists and is safe to call, * FALSE otherwise. + * + * @codeCoverageIgnore This is too exotic */ function function_usable($function_name) { @@ -959,6 +968,8 @@ if (! function_exists('dd')) * Prints a Kint debug report and exits. * * @param array ...$vars + * + * @codeCoverageIgnore Can't be tested ... exits */ function dd(...$vars) { diff --git a/system/Database/Seeder.php b/system/Database/Seeder.php index 441808a88b..1b412e5957 100644 --- a/system/Database/Seeder.php +++ b/system/Database/Seeder.php @@ -149,7 +149,7 @@ class Seeder if ( ! class_exists($class, false)) { - require $path; + require_once $path; } $seeder = new $class($this->config); diff --git a/system/Exceptions/FrameworkException.php b/system/Exceptions/FrameworkException.php index f3ceb9ad47..76646ee3eb 100644 --- a/system/Exceptions/FrameworkException.php +++ b/system/Exceptions/FrameworkException.php @@ -10,6 +10,7 @@ */ class FrameworkException extends \RuntimeException implements ExceptionInterface { + public static function forEmptyBaseURL(): self { return new static('You have an empty or invalid base URL. The baseURL value must be set in Config\App.php, or through the .env file.'); @@ -34,4 +35,5 @@ class FrameworkException extends \RuntimeException implements ExceptionInterface { return new static(lang('Core.noHandlers', [$class])); } + } diff --git a/system/HTTP/Response.php b/system/HTTP/Response.php index 8abfda7a6d..44791bbc45 100644 --- a/system/HTTP/Response.php +++ b/system/HTTP/Response.php @@ -922,6 +922,9 @@ class Response extends Message implements ResponseInterface foreach ($this->cookies as $params) { + // PHP cannot unpack array with string keys + $params = array_values($params); + setcookie(...$params); } } diff --git a/system/Helpers/cookie_helper.php b/system/Helpers/cookie_helper.php index d4c09f7aa8..346404b613 100755 --- a/system/Helpers/cookie_helper.php +++ b/system/Helpers/cookie_helper.php @@ -73,10 +73,7 @@ if ( ! function_exists('set_cookie')) // The following line shows as a syntax error in NetBeans IDE //(\Config\Services::response())->setcookie $response = \Config\Services::response(); - $response->setcookie - ( - $name, $value, $expire, $domain, $path, $prefix, $secure, $httpOnly - ); + $response->setcookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httpOnly); } } diff --git a/system/View/Cell.php b/system/View/Cell.php index b3571eea43..420dc9967b 100644 --- a/system/View/Cell.php +++ b/system/View/Cell.php @@ -77,7 +77,6 @@ class Cell //-------------------------------------------------------------------- - /** * Cell constructor. * @@ -127,7 +126,7 @@ class Cell if ($paramCount === 0) { - if (! empty($paramArray)) + if ( ! empty($paramArray)) { throw ViewException::forMissingCellParameters($class, $method); } @@ -135,7 +134,9 @@ class Cell $output = $instance->{$method}(); } elseif ( - ($paramCount === 1) && ( ( ! array_key_exists($refParams[0]->name, $paramArray)) || (array_key_exists($refParams[0]->name, $paramArray) && count($paramArray) !== 1) ) + ($paramCount === 1) && ( + ( ! array_key_exists($refParams[0]->name, $paramArray)) || + (array_key_exists($refParams[0]->name, $paramArray) && count($paramArray) !== 1) ) ) { $output = $instance->{$method}($paramArray); @@ -162,7 +163,7 @@ class Cell } } - $output = $instance->$method(...$fireArgs); + $output = $instance->$method(...array_values($fireArgs)); } // Can we cache it? if ( ! empty($this->cache) && $ttl !== 0) @@ -205,8 +206,11 @@ class Cell foreach ($params as $p) { - list($key, $val) = explode('=', $p); - $new_params[trim($key)] = trim($val, ', '); + if ( ! empty($p)) + { + list($key, $val) = explode('=', $p); + $new_params[trim($key)] = trim($val, ', '); + } } $params = $new_params; diff --git a/system/View/Parser.php b/system/View/Parser.php index b029e9d376..069ca1733d 100644 --- a/system/View/Parser.php +++ b/system/View/Parser.php @@ -297,26 +297,24 @@ class Parser extends View } //-------------------------------------------------------------------- - - protected function is_assoc($arr) - { - return array_keys($arr) !== range(0, count($arr) - 1); - } - +//FIXME the following method does not appear to be used anywhere, so commented out +// protected function is_assoc($arr) +// { +// return array_keys($arr) !== range(0, count($arr) - 1); +// } //-------------------------------------------------------------------- - - function strpos_all($haystack, $needle) - { - $offset = 0; - $allpos = []; - while (($pos = strpos($haystack, $needle, $offset)) !== FALSE) - { - $offset = $pos + 1; - $allpos[] = $pos; - } - return $allpos; - } - +//FIXME the following method does not appear to be used anywhere, so commented out +// function strpos_all($haystack, $needle) +// { +// $offset = 0; +// $allpos = []; +// while (($pos = strpos($haystack, $needle, $offset)) !== FALSE) +// { +// $offset = $pos + 1; +// $allpos[] = $pos; +// } +// return $allpos; +// } //-------------------------------------------------------------------- /** @@ -524,13 +522,14 @@ class Parser extends View // Parse the PHP itself, or insert an error so they can debug ob_start(); extract($this->data); - $result = eval('?>' . $template . '' . $template . '', 'listErrors(); } - - return $validator->showError($params['field']); - - + return $validator->showError($params['field']); } } diff --git a/tests/_support/Commands/CommandsTestStreamFilter.php b/tests/_support/Commands/CommandsTestStreamFilter.php new file mode 100644 index 0000000000..9618507305 --- /dev/null +++ b/tests/_support/Commands/CommandsTestStreamFilter.php @@ -0,0 +1,17 @@ +data; + $consumed += $bucket->datalen; + } + return PSFS_PASS_ON; + } +} + +stream_filter_register('CommandsTestStreamFilter', 'CodeIgniter\Commands\CommandsTestStreamFilter'); diff --git a/tests/_support/Database/seeds/CITestSeeder.php b/tests/_support/Database/Seeds/CITestSeeder.php similarity index 96% rename from tests/_support/Database/seeds/CITestSeeder.php rename to tests/_support/Database/Seeds/CITestSeeder.php index e7eaed444e..8088eeca21 100644 --- a/tests/_support/Database/seeds/CITestSeeder.php +++ b/tests/_support/Database/Seeds/CITestSeeder.php @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/tests/_support/View/Views/simpler.php b/tests/_support/View/Views/simpler.php new file mode 100644 index 0000000000..0588b62cd1 --- /dev/null +++ b/tests/_support/View/Views/simpler.php @@ -0,0 +1 @@ +

{testString}

\ No newline at end of file diff --git a/tests/system/Commands/CommandsTest.php b/tests/system/Commands/CommandsTest.php new file mode 100644 index 0000000000..00dd6439d6 --- /dev/null +++ b/tests/system/Commands/CommandsTest.php @@ -0,0 +1,63 @@ +stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter'); + + $this->env = new \CodeIgniter\Config\DotEnv(ROOTPATH); + $this->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'; + } + + $_SERVER['argv'] = ['spark', 'list']; + $_SERVER['argc'] = 2; + CLI::init(); + + $this->config = new MockAppConfig(); + $this->request = new \CodeIgniter\HTTP\IncomingRequest($this->config, new \CodeIgniter\HTTP\URI('https://somwhere.com'), null, new UserAgent()); + $this->response = new \CodeIgniter\HTTP\Response($this->config); + $this->runner = new CommandRunner($this->request, $this->response); + } + + public function tearDown() + { + stream_filter_remove($this->stream_filter); + } + + public function testHelpCommand() + { + $this->runner->index(['help']); + $result = CITestStreamFilter::$buffer; + + // make sure the result looks like a command list + $this->assertContains('Displays basic usage information.', $result); + $this->assertContains('command_name', $result); + } + + public function testListCommands() + { + $this->runner->index(['list']); + $result = CITestStreamFilter::$buffer; + + // make sure the result looks like a command list + $this->assertContains('Lists the available commands.', $result); + $this->assertContains('Displays basic usage information.', $result); + } + +} diff --git a/tests/system/Commands/SessionsCommandsTest.php b/tests/system/Commands/SessionsCommandsTest.php new file mode 100644 index 0000000000..7171f8e8ad --- /dev/null +++ b/tests/system/Commands/SessionsCommandsTest.php @@ -0,0 +1,71 @@ +stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter'); + + $this->env = new \CodeIgniter\Config\DotEnv(ROOTPATH); + $this->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'; + } + + $_SERVER['argv'] = ['spark', 'list']; + $_SERVER['argc'] = 2; + CLI::init(); + + $this->config = new MockAppConfig(); + $this->request = new \CodeIgniter\HTTP\IncomingRequest($this->config, new \CodeIgniter\HTTP\URI('https://somwhere.com'), null, new UserAgent()); + $this->response = new \CodeIgniter\HTTP\Response($this->config); + $this->runner = new CommandRunner($this->request, $this->response); + } + + public function tearDown() + { + stream_filter_remove($this->stream_filter); + } + + public function testCreateMigrationCommand() + { + $this->runner->index(['session:migration']); + $result = CITestStreamFilter::$buffer; + + // make sure we end up with a migration class in the right place + // or at least that we claim to have done so + // separate assertions avoid console color codes + $this->assertContains('Created file:', $result); + $this->assertContains('APPPATH/Database/Migrations/', $result); + $this->assertContains('_create_ci_sessions_table.php', $result); + } + + public function testOverriddenCreateMigrationCommand() + { + $_SERVER['argv'] = ['spark','session:migration', '-t', 'mygoodies']; + $_SERVER['argc'] = 4; + CLI::init(); + + $this->runner->index(['session:migration']); + $result = CITestStreamFilter::$buffer; + + // make sure we end up with a migration class in the right place + $this->assertContains('Created file:', $result); + $this->assertContains('APPPATH/Database/Migrations/', $result); + $this->assertContains('_create_mygoodies_table.php', $result); + } + + +} diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index e5ac5b327c..0c88d29c25 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -1,5 +1,16 @@ assertEquals('baz', env('foo', 'baz')); - } + public function testEnvReturnsDefault() + { + $this->assertEquals('baz', env('foo', 'baz')); + } - public function testEnvGetsFromSERVER() - { - $_SERVER['foo'] = 'bar'; + public function testEnvGetsFromSERVER() + { + $_SERVER['foo'] = 'bar'; - $this->assertEquals('bar', env('foo', 'baz')); - } + $this->assertEquals('bar', env('foo', 'baz')); + } - public function testEnvGetsFromENV() - { - $_ENV['foo'] = 'bar'; + public function testEnvGetsFromENV() + { + $_ENV['foo'] = 'bar'; - $this->assertEquals('bar', env('foo', 'baz')); - } + $this->assertEquals('bar', env('foo', 'baz')); + } + + public function testEnvBooleans() + { + $_ENV['p1'] = 'true'; + $_ENV['p2'] = 'false'; + $_ENV['p3'] = 'empty'; + $_ENV['p4'] = 'null'; + + $this->assertTrue(env('p1')); + $this->assertFalse(env('p2')); + $this->assertEmpty(env('p3')); + $this->assertNull(env('p4')); + } + + // ------------------------------------------------------------------------ public function testRedirectReturnsRedirectResponse() { $_SERVER['REQUEST_METHOD'] = 'GET'; $response = $this->createMock(\CodeIgniter\HTTP\Response::class); - $routes = new \CodeIgniter\Router\RouteCollection(new \Tests\Support\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); $routes->add('home/base', 'Controller::index', ['as' => 'base']); $response->method('redirect') - ->will($this->returnArgument(0)); + ->will($this->returnArgument(0)); $this->assertInstanceOf(\CodeIgniter\HTTP\RedirectResponse::class, redirect('base')); - } + } + + public function testRedirectDefault() + { + $this->assertInstanceOf(\CodeIgniter\HTTP\RedirectResponse::class, redirect()); + } + + // ------------------------------------------------------------------------ + + public function testView() + { + $data = [ + 'testString' => 'bar', + 'bar' => 'baz', + ]; + $expected = '

bar

'; + $this->assertContains($expected, view('\Tests\Support\View\Views\simple', $data, [])); + } + + public function testViewSavedData() + { + $data = [ + 'testString' => 'bar', + 'bar' => 'baz', + ]; + $expected = '

bar

'; + $this->assertContains($expected, view('\Tests\Support\View\Views\simple', $data, ['saveData' => true])); + $this->assertContains($expected, view('\Tests\Support\View\Views\simple')); + } + + // ------------------------------------------------------------------------ + + public function testViewCell() + { + $expected = 'Hello'; + $this->assertEquals($expected, view_cell('\CodeIgniter\View\SampleClass::hello')); + } + + // ------------------------------------------------------------------------ + + public function testEscapeBadContext() + { + $this->expectException(InvalidArgumentException::class); + esc(['width' => '800', 'height' => '600'], 'bogus'); + } + + // ------------------------------------------------------------------------ + + public function testSessionInstance() + { + $this->assertInstanceOf(CodeIgniter\Session\Session::class, session()); + } + + public function testSessionVariable() + { + $_SESSION['notbogus'] = 'Hi there'; + $this->assertEquals('Hi there', session('notbogus')); + } + + public function testSessionVariableNotThere() + { + $_SESSION['bogus'] = 'Hi there'; + $this->assertEquals(null, session('notbogus')); + } + + // ------------------------------------------------------------------------ + + public function testSingleService() + { + $timer1 = single_service('timer'); + $timer2 = single_service('timer'); + $this->assertFalse($timer1 === $timer2); + } + + // ------------------------------------------------------------------------ + + public function testRouteTo() + { + // prime the pump + $routes = service('routes'); + $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2'); + + $this->assertEquals('/path/string/to/13', route_to('myController::goto', 'string', 13)); + } + + // ------------------------------------------------------------------------ + + public function testInvisible() + { + $this->assertEquals('Javascript', remove_invisible_characters("Java\0script")); + } + + public function testInvisibleEncoded() + { + $this->assertEquals('Javascript', remove_invisible_characters("Java%0cscript", true)); + } + + // ------------------------------------------------------------------------ + + public function testAppTimezone() + { + $this->assertEquals('America/Chicago', app_timezone()); + } + + // ------------------------------------------------------------------------ + + public function testCSRFToken() + { + $this->assertEquals('csrf_test_name', csrf_token()); + } + + public function testHash() + { + $this->assertEquals(32, strlen(csrf_hash())); + } + + public function testCSRFField() + { + $this->assertContains('config = new App(); + $this->config->baseURL = 'http://example.com'; + + $this->routes = new RouteCollection(new MockFileLocator(new Autoload())); + Services::injectMock('routes', $this->routes); + + $this->request = new MockIncomingRequest($this->config, new URI('http://example.com'), null, new UserAgent()); + Services::injectMock('request', $this->request); + + // setup & ask for a redirect... + $_SESSION = []; + $_GET = ['foo' => 'bar']; + $_POST = ['bar' => 'baz', 'zibble' => serialize('fritz')]; + + $response = new RedirectResponse(new App()); + $returned = $response->withInput(); + + $this->assertEquals('bar', old('foo')); // regular parameter + $this->assertEquals('doo', old('yabba dabba', 'doo')); // non-existing parameter + $this->assertEquals('fritz', old('zibble')); // serialized parameter + } + + // ------------------------------------------------------------------------ + + public function testReallyWritable() + { + // cannot test fully on *nix + $this->assertTrue(is_really_writable(WRITEPATH)); + } + + // ------------------------------------------------------------------------ + + public function testSlashItem() + { + $this->assertEquals('/', slash_item('cookiePath')); // slash already there + $this->assertEquals('', slash_item('cookieDomain')); // empty, so untouched + $this->assertEquals('en/', slash_item('defaultLocale')); // slash appended + } } diff --git a/tests/system/Database/Live/AliasTest.php b/tests/system/Database/Live/AliasTest.php index b5b933ca7b..f4d1f588c8 100644 --- a/tests/system/Database/Live/AliasTest.php +++ b/tests/system/Database/Live/AliasTest.php @@ -6,7 +6,7 @@ class AliasTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testAlias() { diff --git a/tests/system/Database/Live/CIDbTestCaseTest.php b/tests/system/Database/Live/CIDbTestCaseTest.php index a025ad33a4..3cd083edd1 100644 --- a/tests/system/Database/Live/CIDbTestCaseTest.php +++ b/tests/system/Database/Live/CIDbTestCaseTest.php @@ -9,7 +9,7 @@ class CIDbTestCaseTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testHasInDatabase() { diff --git a/tests/system/Database/Live/CountTest.php b/tests/system/Database/Live/CountTest.php index 804e860879..510061d7b9 100644 --- a/tests/system/Database/Live/CountTest.php +++ b/tests/system/Database/Live/CountTest.php @@ -9,7 +9,7 @@ class CountTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testCountReturnsZeroWithNoResults() { diff --git a/tests/system/Database/Live/DeleteTest.php b/tests/system/Database/Live/DeleteTest.php index 048852ba21..6aa3578e04 100644 --- a/tests/system/Database/Live/DeleteTest.php +++ b/tests/system/Database/Live/DeleteTest.php @@ -10,7 +10,7 @@ class DeleteTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testDeleteThrowExceptionWithNoCriteria() { diff --git a/tests/system/Database/Live/EmptyTest.php b/tests/system/Database/Live/EmptyTest.php index 33f53e8ef1..32575a99a9 100644 --- a/tests/system/Database/Live/EmptyTest.php +++ b/tests/system/Database/Live/EmptyTest.php @@ -9,7 +9,7 @@ class EmptyTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testEmpty() { diff --git a/tests/system/Database/Live/ForgeTest.php b/tests/system/Database/Live/ForgeTest.php index b570467250..2492376542 100644 --- a/tests/system/Database/Live/ForgeTest.php +++ b/tests/system/Database/Live/ForgeTest.php @@ -9,7 +9,7 @@ class ForgeTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function setUp() { diff --git a/tests/system/Database/Live/FromTest.php b/tests/system/Database/Live/FromTest.php index 9d3740f61f..1df87f02b6 100644 --- a/tests/system/Database/Live/FromTest.php +++ b/tests/system/Database/Live/FromTest.php @@ -9,7 +9,7 @@ class FromTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testFromCanAddTables() { diff --git a/tests/system/Database/Live/GetTest.php b/tests/system/Database/Live/GetTest.php index 85349437ae..785a4753a8 100644 --- a/tests/system/Database/Live/GetTest.php +++ b/tests/system/Database/Live/GetTest.php @@ -9,7 +9,7 @@ class GetTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testGet() { diff --git a/tests/system/Database/Live/GroupTest.php b/tests/system/Database/Live/GroupTest.php index 65dce2c6a5..5be00607d5 100644 --- a/tests/system/Database/Live/GroupTest.php +++ b/tests/system/Database/Live/GroupTest.php @@ -9,7 +9,7 @@ class GroupTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testGroupBy() { diff --git a/tests/system/Database/Live/IncrementTest.php b/tests/system/Database/Live/IncrementTest.php index c5d7209cf0..69d1f6f599 100644 --- a/tests/system/Database/Live/IncrementTest.php +++ b/tests/system/Database/Live/IncrementTest.php @@ -9,7 +9,7 @@ class IncrementTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testIncrement() { diff --git a/tests/system/Database/Live/InsertTest.php b/tests/system/Database/Live/InsertTest.php index 207c64627d..f29377e982 100644 --- a/tests/system/Database/Live/InsertTest.php +++ b/tests/system/Database/Live/InsertTest.php @@ -9,7 +9,7 @@ class InsertTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testInsert() { diff --git a/tests/system/Database/Live/JoinTest.php b/tests/system/Database/Live/JoinTest.php index 5f3fb6c770..da3cd07026 100644 --- a/tests/system/Database/Live/JoinTest.php +++ b/tests/system/Database/Live/JoinTest.php @@ -9,7 +9,7 @@ class JoinTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testSimpleJoin() { diff --git a/tests/system/Database/Live/LikeTest.php b/tests/system/Database/Live/LikeTest.php index 0922d4cc80..2e9d539a9b 100644 --- a/tests/system/Database/Live/LikeTest.php +++ b/tests/system/Database/Live/LikeTest.php @@ -9,7 +9,7 @@ class LikeTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testLikeDefault() { diff --git a/tests/system/Database/Live/LimitTest.php b/tests/system/Database/Live/LimitTest.php index e7669ebdd5..ad5359b41e 100644 --- a/tests/system/Database/Live/LimitTest.php +++ b/tests/system/Database/Live/LimitTest.php @@ -9,7 +9,7 @@ class LimitTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testLimit() { diff --git a/tests/system/Database/Live/ModelTest.php b/tests/system/Database/Live/ModelTest.php index 38807592f0..a42cd49781 100644 --- a/tests/system/Database/Live/ModelTest.php +++ b/tests/system/Database/Live/ModelTest.php @@ -20,7 +20,7 @@ class ModelTest extends CIDatabaseTestCase protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function setUp() { diff --git a/tests/system/Database/Live/OrderTest.php b/tests/system/Database/Live/OrderTest.php index 512b7edb85..c239a10e87 100644 --- a/tests/system/Database/Live/OrderTest.php +++ b/tests/system/Database/Live/OrderTest.php @@ -9,7 +9,7 @@ class OrderTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testOrderAscending() { diff --git a/tests/system/Database/Live/PreparedQueryTest.php b/tests/system/Database/Live/PreparedQueryTest.php index 7dc07b35a8..f283f3cc65 100644 --- a/tests/system/Database/Live/PreparedQueryTest.php +++ b/tests/system/Database/Live/PreparedQueryTest.php @@ -10,7 +10,7 @@ class PreparedQueryTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; //-------------------------------------------------------------------- diff --git a/tests/system/Database/Live/SelectTest.php b/tests/system/Database/Live/SelectTest.php index b2829baca3..39c1d47abb 100644 --- a/tests/system/Database/Live/SelectTest.php +++ b/tests/system/Database/Live/SelectTest.php @@ -10,7 +10,7 @@ class SelectTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; //-------------------------------------------------------------------- diff --git a/tests/system/Database/Live/UpdateTest.php b/tests/system/Database/Live/UpdateTest.php index b7e4f0735d..729f1ba96a 100644 --- a/tests/system/Database/Live/UpdateTest.php +++ b/tests/system/Database/Live/UpdateTest.php @@ -10,7 +10,7 @@ class UpdateTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testUpdateSetsAllWithoutWhere() { diff --git a/tests/system/Database/Live/WhereTest.php b/tests/system/Database/Live/WhereTest.php index 84a3e778eb..aeea97b39b 100644 --- a/tests/system/Database/Live/WhereTest.php +++ b/tests/system/Database/Live/WhereTest.php @@ -9,7 +9,7 @@ class WhereTest extends CIDatabaseTestCase { protected $refresh = true; - protected $seed = 'CITestSeeder'; + protected $seed = 'Tests\Support\Database\Seeds\CITestSeeder'; public function testWhereSimpleKeyValue() { diff --git a/tests/system/View/CellTest.php b/tests/system/View/CellTest.php index 75b9742de8..e9a5ff09ad 100644 --- a/tests/system/View/CellTest.php +++ b/tests/system/View/CellTest.php @@ -1,12 +1,14 @@ cache = new MockHandler(); - $this->cell = new Cell($this->cache); + $this->cell = new Cell($this->cache); } //-------------------------------------------------------------------- public function testPrepareParamsReturnsEmptyArrayWithInvalidParam() { - $this->assertEquals([], $this->cell->prepareParams(1.023)); + $this->assertEquals([], $this->cell->prepareParams(1.023)); } //-------------------------------------------------------------------- public function testPrepareParamsReturnsNullWithEmptyString() { - $this->assertEquals([], $this->cell->prepareParams('')); + $this->assertEquals([], $this->cell->prepareParams('')); } //-------------------------------------------------------------------- public function testPrepareParamsReturnsSelfWhenArray() { - $object = ['one' => 'two', 'three' => 'four']; + $object = ['one' => 'two', 'three' => 'four']; $this->assertEquals($object, $this->cell->prepareParams($object)); } @@ -51,14 +53,14 @@ class CellTest extends \CIUnitTestCase public function testPrepareParamsReturnsEmptyArrayWithEmptyArray() { - $this->assertEquals([], $this->cell->prepareParams([])); + $this->assertEquals([], $this->cell->prepareParams([])); } //-------------------------------------------------------------------- public function testPrepareParamsReturnsArrayWithString() { - $params = 'one=two three=four'; + $params = 'one=two three=four'; $expected = ['one' => 'two', 'three' => 'four']; $this->assertEquals($expected, $this->cell->prepareParams($params)); @@ -95,7 +97,6 @@ class CellTest extends \CIUnitTestCase } //-------------------------------------------------------------------- - //-------------------------------------------------------------------- // Render //-------------------------------------------------------------------- @@ -129,18 +130,96 @@ class CellTest extends \CIUnitTestCase //-------------------------------------------------------------------- - public function testOptionsEmptyArray() - { - $params = []; - $expected = []; + public function testOptionsEmptyArray() + { + $params = []; + $expected = []; - $this->assertEquals(implode(',', $expected), $this->cell->render('\CodeIgniter\View\SampleClass::staticEcho', $params)); - } + $this->assertEquals(implode(',', $expected), $this->cell->render('\CodeIgniter\View\SampleClass::staticEcho', $params)); + } - public function testOptionsNoParams() - { - $expected = []; + public function testOptionsNoParams() + { + $expected = []; + + $this->assertEquals(implode(',', $expected), $this->cell->render('\CodeIgniter\View\SampleClass::staticEcho')); + } + + public function testCellEmptyParams() + { + $params = ','; + $expected = 'Hello World'; + + $this->assertEquals($expected, $this->cell->render('\CodeIgniter\View\SampleClass::index', $params)); + } + + //-------------------------------------------------------------------- + + public function testCellClassMissing() + { + $this->expectException(ViewException::class); + $params = 'one=two,three=four'; + $expected = ['one' => 'two', 'three' => 'four']; + + $this->assertEquals(implode(',', $expected), $this->cell->render('::echobox', $params)); + } + + public function testCellMethodMissing() + { + $this->expectException(ViewException::class); + $params = 'one=two,three=four'; + $expected = ['one' => 'two', 'three' => 'four']; + + $this->assertEquals(implode(',', $expected), $this->cell->render('\CodeIgniter\View\SampleClass::', $params)); + } + + public function testCellBadClass() + { + $this->expectException(ViewException::class); + $params = 'one=two,three=four'; + $expected = 'Hello World'; + + $this->assertEquals($expected, $this->cell->render('\CodeIgniter\View\GoodQuestion::', $params)); + } + + public function testCellBadMethod() + { + $this->expectException(ViewException::class); + $params = 'one=two,three=four'; + $expected = 'Hello World'; + + $this->assertEquals($expected, $this->cell->render('\CodeIgniter\View\SampleClass::notThere', $params)); + } + + //-------------------------------------------------------------------- + + public function testRenderCached() + { + $params = 'one=two,three=four'; + $expected = ['one' => 'two', 'three' => 'four']; + + $this->assertEquals(implode(',', $expected), $this->cell->render('\CodeIgniter\View\SampleClass::echobox', $params, 60, 'rememberme')); + $params = 'one=six,three=five'; + $this->assertEquals(implode(',', $expected), $this->cell->render('\CodeIgniter\View\SampleClass::echobox', $params, 1, 'rememberme')); + } + + //-------------------------------------------------------------------- + + public function testParametersMatch() + { + $params = ['p1' => 'one', 'p2' => 'two', 'p4' => 'three']; + $expected = 'Right on'; + + $this->assertEquals($expected, $this->cell->render('\CodeIgniter\View\SampleClass::work', $params)); + } + + public function testParametersDontMatch() + { + $this->expectException(ViewException::class); + $params = 'p1=one,p2=two,p3=three'; + $expected = 'Right on'; + + $this->assertEquals($expected, $this->cell->render('\CodeIgniter\View\SampleClass::work', $params)); + } - $this->assertEquals(implode(',', $expected), $this->cell->render('\CodeIgniter\View\SampleClass::staticEcho')); - } } diff --git a/tests/system/View/ParserFilterTest.php b/tests/system/View/ParserFilterTest.php index dc34d4c348..b37168567c 100644 --- a/tests/system/View/ParserFilterTest.php +++ b/tests/system/View/ParserFilterTest.php @@ -159,6 +159,39 @@ class ParserFilterTest extends \CIUnitTestCase $this->assertEquals("The quick red fox jumped over the lazy brown dog", $parser->renderString($template)); } + public function testHighlightCode() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + + $data = [ + 'value1' => 'Sincerely' + ]; + $parser->setData($data); + + $template = '{ value1|highlight_code }'; + $expected = << +Sincerely  + + +EOF; + $this->assertEquals($expected, $parser->renderString($template)); + } + + public function testProse() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + + $data = [ + 'value1' => 'Sincerely\nMe' + ]; + $parser->setData($data); + + $template = '{ value1|prose }'; + $expected = '

Sincerely\nMe

'; + $this->assertEquals($expected, $parser->renderString($template)); + } + //-------------------------------------------------------------------- public function testLimitChars() @@ -249,10 +282,10 @@ class ParserFilterTest extends \CIUnitTestCase 'value1' => 5.55, ]; - $template = '{ value1|round(1) } { value1|round(1, common) } { value1|round(ceil) } { value1|round(floor) }'; + $template = '{ value1|round(1) } { value1|round(1, common) } { value1|round(ceil) } { value1|round(floor) } { value1|round(unknown) }'; $parser->setData($data); - $this->assertEquals('5.6 5.6 6 5', $parser->renderString($template)); + $this->assertEquals('5.6 5.6 6 5 5.55', $parser->renderString($template)); } //-------------------------------------------------------------------- diff --git a/tests/system/View/ParserPluginTest.php b/tests/system/View/ParserPluginTest.php index 009b0e5c18..5f8e03d977 100644 --- a/tests/system/View/ParserPluginTest.php +++ b/tests/system/View/ParserPluginTest.php @@ -1,6 +1,7 @@ loader = new \CodeIgniter\Autoloader\FileLocator(new \Config\Autoload()); - $this->viewsDir = __DIR__.'/Views'; - $this->config = new Config\View(); + $this->loader = new \CodeIgniter\Autoloader\FileLocator(new \Config\Autoload()); + $this->viewsDir = __DIR__ . '/Views'; + $this->config = new Config\View(); } // -------------------------------------------------------------------- @@ -55,9 +56,9 @@ class ParserTest extends \CIUnitTestCase public function testParseString() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Page Title', - 'body' => 'Lorem ipsum dolor sit amet.', + $data = [ + 'title' => 'Page Title', + 'body' => 'Lorem ipsum dolor sit amet.', ]; $template = "{title}\n{body}"; @@ -73,14 +74,14 @@ class ParserTest extends \CIUnitTestCase public function testParseStringMissingData() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Page Title', - 'body' => 'Lorem ipsum dolor sit amet.', + $data = [ + 'title' => 'Page Title', + 'body' => 'Lorem ipsum dolor sit amet.', ]; $template = "{title}\n{body}\n{name}"; - $result = implode("\n", $data)."\n{name}"; + $result = implode("\n", $data) . "\n{name}"; $parser->setData($data); $this->assertEquals($result, $parser->renderString($template)); @@ -91,10 +92,10 @@ class ParserTest extends \CIUnitTestCase public function testParseStringUnusedData() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Page Title', - 'body' => 'Lorem ipsum dolor sit amet.', - 'name' => 'Someone', + $data = [ + 'title' => 'Page Title', + 'body' => 'Lorem ipsum dolor sit amet.', + 'name' => 'Someone', ]; $template = "{title}\n{body}"; @@ -115,26 +116,26 @@ class ParserTest extends \CIUnitTestCase // -------------------------------------------------------------------- - public function testParseArraySingle() - { - $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Super Heroes', - 'powers' => [ - ['invisibility' => 'yes', 'flying' => 'no'], - ], - ]; + public function testParseArraySingle() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $data = [ + 'title' => 'Super Heroes', + 'powers' => [ + ['invisibility' => 'yes', 'flying' => 'no'], + ], + ]; - $template = "{ title }\n{ powers }{invisibility}\n{flying}{/powers}"; + $template = "{ title }\n{ powers }{invisibility}\n{flying}{/powers}"; - $parser->setData($data); - $this->assertEquals("Super Heroes\nyes\nno", $parser->renderString($template)); - } + $parser->setData($data); + $this->assertEquals("Super Heroes\nyes\nno", $parser->renderString($template)); + } public function testParseArrayMulti() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ + $data = [ 'powers' => [ ['invisibility' => 'yes', 'flying' => 'no'], ], @@ -146,13 +147,52 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals("yes\nno\nsecond: yes no", $parser->renderString($template)); } + public function testParseArrayNested() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $data = [ + 'title' => 'Super Heroes', + 'powers' => [ + ['invisibility' => 'yes', 'flying' => [ + ['by' => 'plane', 'with' => 'broomstick', 'scared' => 'yes'] + ]], + ], + ]; + + $template = "{ title }\n{ powers }{invisibility}\n{flying}{by} {with}{/flying}{/powers}"; + + $parser->setData($data); + $this->assertEquals("Super Heroes\nyes\nplane broomstick", $parser->renderString($template)); + } + + public function testParseArrayNestedObject() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $eagle = new stdClass(); + $eagle->name = 'Baldy'; + $eagle->home = 'Rockies'; + $data = [ + 'birds' => [[ + 'pop' => $eagle, + 'mom' => 'Owl', + 'kids' => ['Tom', 'Dick', 'Harry'], + 'home' => opendir('.'), + ]], + ]; + + $template = "{ birds }{mom} and {pop} work at {home}{/birds}"; + + $parser->setData($data); + $this->assertEquals("Owl and Class: stdClass work at Resource", $parser->renderString($template)); + } + // -------------------------------------------------------------------- public function testParseLoop() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Super Heroes', + $data = [ + 'title' => 'Super Heroes', 'powers' => [ ['name' => 'Tom'], ['name' => 'Dick'], @@ -171,15 +211,15 @@ class ParserTest extends \CIUnitTestCase public function testMismatchedVarPair() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Super Heroes', + $data = [ + 'title' => 'Super Heroes', 'powers' => [ ['invisibility' => 'yes', 'flying' => 'no'], ], ]; $template = "{title}\n{powers}{invisibility}\n{flying}"; - $result = "Super Heroes\n{powers}{invisibility}\n{flying}"; + $result = "Super Heroes\n{powers}{invisibility}\n{flying}"; $parser->setData($data); $this->assertEquals($result, $parser->renderString($template)); @@ -190,15 +230,15 @@ class ParserTest extends \CIUnitTestCase public function escValueTypes() { return [ - 'scalar' => [42], - 'string' => ['George'], - 'scalarlist' => [[1, 2, 17, -4]], - 'stringlist' => [['George', 'Paul', 'John', 'Ringo']], - 'associative' => [['name' => 'George', 'role' => 'guitar']], - 'compound' => [['name' => 'George', 'address' => ['line1' => '123 Some St', 'planet' => 'Naboo']]], - 'pseudo' => [ + 'scalar' => [42], + 'string' => ['George'], + 'scalarlist' => [[1, 2, 17, -4]], + 'stringlist' => [['George', 'Paul', 'John', 'Ringo']], + 'associative' => [['name' => 'George', 'role' => 'guitar']], + 'compound' => [['name' => 'George', 'address' => ['line1' => '123 Some St', 'planet' => 'Naboo']]], + 'pseudo' => [ [ - 'name' => 'George', + 'name' => 'George', 'emails' => [ ['email' => 'me@here.com', 'type' => 'home'], ['email' => 'me@there.com', 'type' => 'work'], @@ -245,6 +285,34 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('http%3A%2F%2Ffoo.com', $parser->renderString($template)); } + public function testNoEscapingSetData() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + + $template = '{ foo | noescape}'; + + $parser->setData(['foo' => 'http://foo.com'], 'unknown'); + $this->assertEquals('http://foo.com', $parser->renderString($template)); + } + + public function testAutoEscaping() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['foo' => 'http://foo.com'], 'unknown'); + + $this->assertEquals('html', $parser->shouldAddEscaping('{ foo | this | that }')); + } + + public function testAutoEscapingNot() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['foo' => 'http://foo.com'], 'unknown'); + + $this->assertEquals(false, $parser->shouldAddEscaping('{ foo | noescape }')); + } + + //-------------------------------------------------------------------- + public function testFilterWithNoArgument() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); @@ -259,8 +327,6 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('<script>alert("ci4")</script>', $parser->renderString($template)); } - //-------------------------------------------------------------------- - public function testFilterWithArgument() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); @@ -284,7 +350,7 @@ class ParserTest extends \CIUnitTestCase $parser = new Parser($this->config, $this->viewsDir, $this->loader); $data = [ - 'title' => '', + 'title' => '', 'powers' => [ ['link' => "Link"], ], @@ -295,35 +361,33 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('<script>Heroes</script> <a href='test'>Link</a>', $parser->renderString($template)); } - //-------------------------------------------------------------------- + public function testParserNoEscape() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); - public function testParserNoEscape() - { - $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $data = [ + 'title' => '', + ]; - $data = [ - 'title' => '', - ]; - - $template = "{! title!}"; - $parser->setData($data); - $this->assertEquals('', $parser->renderString($template)); - } + $template = "{! title!}"; + $parser->setData($data); + $this->assertEquals('', $parser->renderString($template)); + } //-------------------------------------------------------------------- public function testIgnoresComments() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Super Heroes', + $data = [ + 'title' => 'Super Heroes', 'powers' => [ ['invisibility' => 'yes', 'flying' => 'no'], ], ]; $template = "{# Comments #}{title}\n{powers}{invisibility}\n{flying}"; - $result = "Super Heroes\n{powers}{invisibility}\n{flying}"; + $result = "Super Heroes\n{powers}{invisibility}\n{flying}"; $parser->setData($data); $this->assertEquals($result, $parser->renderString($template)); @@ -334,15 +398,15 @@ class ParserTest extends \CIUnitTestCase public function testNoParse() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Super Heroes', + $data = [ + 'title' => 'Super Heroes', 'powers' => [ ['invisibility' => 'yes', 'flying' => 'no'], ], ]; $template = "{noparse}{title}\n{powers}{invisibility}\n{flying}{/noparse}"; - $result = "{title}\n{powers}{invisibility}\n{flying}"; + $result = "{title}\n{powers}{invisibility}\n{flying}"; $parser->setData($data); $this->assertEquals($result, $parser->renderString($template)); @@ -353,9 +417,9 @@ class ParserTest extends \CIUnitTestCase public function testIfConditionalTrue() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'doit' => true, - 'dontdoit' => false + $data = [ + 'doit' => true, + 'dontdoit' => false ]; $template = "{if doit}Howdy{endif}{ if dontdoit === false}Welcome{ endif }"; @@ -364,12 +428,10 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('HowdyWelcome', $parser->renderString($template)); } - //-------------------------------------------------------------------- - public function testElseConditionalFalse() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ + $data = [ 'doit' => true, ]; @@ -379,12 +441,10 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('Howdy', $parser->renderString($template)); } - //-------------------------------------------------------------------- - public function testElseConditionalTrue() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ + $data = [ 'doit' => false, ]; @@ -394,14 +454,12 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('Welcome', $parser->renderString($template)); } - //-------------------------------------------------------------------- - public function testElseifConditionalTrue() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'doit' => false, - 'dontdoit' => true + $data = [ + 'doit' => false, + 'dontdoit' => true ]; $template = "{if doit}Howdy{elseif dontdoit}Welcome{ endif }"; @@ -412,6 +470,24 @@ class ParserTest extends \CIUnitTestCase //-------------------------------------------------------------------- + public function testConditionalBadSyntax() + { + $this->expectException(ViewException::class); + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $data = [ + 'doit' => true, + 'dontdoit' => false + ]; + + // the template is purposefully malformed + $template = "{if doit}Howdy{elseif doit}Welcome{ endif )}"; + + $parser->setData($data); + $this->assertEquals('HowdyWelcome', $parser->renderString($template)); + } + + //-------------------------------------------------------------------- + public function testWontParsePHP() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); @@ -425,9 +501,9 @@ class ParserTest extends \CIUnitTestCase public function testParseHandlesSpaces() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Page Title', - 'body' => 'Lorem ipsum dolor sit amet.', + $data = [ + 'title' => 'Page Title', + 'body' => 'Lorem ipsum dolor sit amet.', ]; $template = "{ title}\n{ body }"; @@ -440,75 +516,77 @@ class ParserTest extends \CIUnitTestCase // -------------------------------------------------------------------- - public function testParseRuns() - { - $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'title' => 'Page Title', - 'body' => 'Lorem ipsum dolor sit amet.', - ]; + public function testParseRuns() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $data = [ + 'title' => 'Page Title', + 'body' => 'Lorem ipsum dolor sit amet.', + ]; - $template = "{ title}\n{ body }"; + $template = "{ title}\n{ body }"; - $result = implode("\n", $data); + $result = implode("\n", $data); - $parser->setData($data); - $this->assertEquals($result, $parser->renderString($template)); - } + $parser->setData($data); + $this->assertEquals($result, $parser->renderString($template)); + } - //-------------------------------------------------------------------- + //-------------------------------------------------------------------- - /** - * @group parserplugins - */ - public function testCanAddAndRemovePlugins() - { - $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $parser->addPlugin('first', function($str){ return $str; }); + /** + * @group parserplugins + */ + public function testCanAddAndRemovePlugins() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->addPlugin('first', function($str) { + return $str; + }); - $setParsers = $this->getPrivateProperty($parser, 'plugins'); + $setParsers = $this->getPrivateProperty($parser, 'plugins'); - $this->assertArrayHasKey('first', $setParsers); + $this->assertArrayHasKey('first', $setParsers); - $parser->removePlugin('first'); + $parser->removePlugin('first'); - $setParsers = $this->getPrivateProperty($parser, 'plugins'); + $setParsers = $this->getPrivateProperty($parser, 'plugins'); - $this->assertArrayNotHasKey('first', $setParsers); - } + $this->assertArrayNotHasKey('first', $setParsers); + } - //-------------------------------------------------------------------- + //-------------------------------------------------------------------- - /** - * @group parserplugins - */ - public function testParserPluginNoMatches() - { - $parser = new Parser($this->config, $this->viewsDir, $this->loader); + /** + * @group parserplugins + */ + public function testParserPluginNoMatches() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $template = "hit:it"; + $template = "hit:it"; - $this->assertEquals("hit:it", $parser->renderString($template)); - } + $this->assertEquals("hit:it", $parser->renderString($template)); + } - //-------------------------------------------------------------------- + //-------------------------------------------------------------------- - /** - * @group parserplugins - */ - public function testParserPluginNoParams() - { - $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $parser->addPlugin('hit:it', function($str){ - return str_replace('here', "Hip to the Hop", $str); - }, true); + /** + * @group parserplugins + */ + public function testParserPluginNoParams() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->addPlugin('hit:it', function($str) { + return str_replace('here', "Hip to the Hop", $str); + }, true); - $template = "{+ hit:it +} stuff here {+ /hit:it +}"; + $template = "{+ hit:it +} stuff here {+ /hit:it +}"; - $this->assertEquals(" stuff Hip to the Hop ", $parser->renderString($template)); - } + $this->assertEquals(" stuff Hip to the Hop ", $parser->renderString($template)); + } - //-------------------------------------------------------------------- + //-------------------------------------------------------------------- /** * @group parserplugins @@ -516,15 +594,15 @@ class ParserTest extends \CIUnitTestCase public function testParserPluginParams() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $parser->addPlugin('growth', function($str, array $params){ + $parser->addPlugin('growth', function($str, array $params) { $step = $params['step'] ?? 1; $count = $params['count'] ?? 2; $out = ''; - for ($i=1; $i <= $count; $i++) + for ($i = 1; $i <= $count; $i ++ ) { - $out .= " ".$i * $step; + $out .= " " . $i * $step; } return $out; @@ -543,7 +621,7 @@ class ParserTest extends \CIUnitTestCase public function testParserSingleTag() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $parser->addPlugin('hit:it', function(){ + $parser->addPlugin('hit:it', function() { return "Hip to the Hop"; }, false); @@ -552,15 +630,13 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals("Hip to the Hop", $parser->renderString($template)); } - //-------------------------------------------------------------------- - /** * @group parserplugins */ public function testParserSingleTagWithParams() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $parser->addPlugin('hit:it', function(array $params=[]){ + $parser->addPlugin('hit:it', function(array $params = []) { return "{$params['first']} to the {$params['last']}"; }, false); @@ -569,15 +645,13 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals("foo to the bar", $parser->renderString($template)); } - //-------------------------------------------------------------------- - /** * @group parserplugins */ public function testParserSingleTagWithSingleParams() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $parser->addPlugin('hit:it', function(array $params=[]){ + $parser->addPlugin('hit:it', function(array $params = []) { return "{$params[0]} to the {$params[1]}"; }, false); @@ -586,15 +660,13 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals("foo to the bar", $parser->renderString($template)); } - //-------------------------------------------------------------------- - /** * @group parserplugins */ public function testParserSingleTagWithQuotedParams() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $parser->addPlugin('count', function(array $params=[]){ + $parser->addPlugin('count', function(array $params = []) { $out = ''; foreach ($params as $index => $param) @@ -618,7 +690,7 @@ class ParserTest extends \CIUnitTestCase public function testParseLoopWithDollarSign() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ + $data = [ 'books' => [ ['price' => '12.50'], ], @@ -630,5 +702,65 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals("

Price $: 12.50

", $parser->renderString($template)); } - // -------------------------------------------------------------------- + //-------------------------------------------------------------------- + + public function testCachedRender() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setVar('teststring', 'Hello World'); + + $expected = '

Hello World

'; + $this->assertEquals($expected, $parser->render('template1', ['cache' => 10, 'cache_name' => 'HelloWorld'])); + // this second renderings should go thru the cache + $this->assertEquals($expected, $parser->render('template1', ['cache' => 10, 'cache_name' => 'HelloWorld'])); + } + + //-------------------------------------------------------------------- + + public function testRenderFindsView() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['testString' => 'Hello World']); + + $expected = '

Hello World

'; + $this->assertEquals($expected, $parser->render('Simpler')); + } + + public function testRenderCantFindView() + { + $this->expectException(ViewException::class); + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['testString' => 'Hello World']); + + $expected = '

Hello World

'; + $result = $parser->render('Simplest'); + } + + //-------------------------------------------------------------------- + + public function testRenderSavingData() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['testString' => 'Hello World']); + + $expected = '

Hello World

'; + $this->assertEquals($expected, $parser->render('Simpler', [], true)); + $this->assertArrayHasKey('testString', $parser->getData()); + $this->assertEquals($expected, $parser->render('Simpler', [], false)); + $this->assertArrayNotHasKey('testString', $parser->getData()); + } + + public function testRenderStringSavingData() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['testString' => 'Hello World']); + + $expected = '

Hello World

'; + $pattern = '

{testString}

'; + $this->assertEquals($expected, $parser->renderString($pattern, [], true)); + $this->assertArrayHasKey('testString', $parser->getData()); + $this->assertEquals($expected, $parser->renderString($pattern, [], false)); + $this->assertArrayNotHasKey('testString', $parser->getData()); + } + } diff --git a/tests/system/View/SampleClass.php b/tests/system/View/SampleClass.php index 88dd413b6e..28de16fe2c 100644 --- a/tests/system/View/SampleClass.php +++ b/tests/system/View/SampleClass.php @@ -8,6 +8,11 @@ */ class SampleClass { + public function index() + { + return 'Hello World'; + } + public function hello() { return 'Hello'; @@ -39,5 +44,7 @@ class SampleClass { //-------------------------------------------------------------------- - + public function work($p1, $p2, $p4) { + return 'Right on'; + } } \ No newline at end of file diff --git a/tests/system/View/ViewTest.php b/tests/system/View/ViewTest.php index 31432ac38d..681dbc631b 100644 --- a/tests/system/View/ViewTest.php +++ b/tests/system/View/ViewTest.php @@ -4,6 +4,7 @@ use CodeIgniter\View\View; class ViewTest extends \CIUnitTestCase { + protected $loader; protected $viewsDir; protected $config; @@ -15,8 +16,8 @@ class ViewTest extends \CIUnitTestCase parent::setUp(); $this->loader = new \CodeIgniter\Autoloader\FileLocator(new \Config\Autoload()); - $this->viewsDir = __DIR__.'/Views'; - $this->config = new Config\View(); + $this->viewsDir = __DIR__ . '/Views'; + $this->config = new Config\View(); } //-------------------------------------------------------------------- @@ -30,8 +31,6 @@ class ViewTest extends \CIUnitTestCase $this->assertEquals(['foo' => 'bar'], $view->getData()); } - //-------------------------------------------------------------------- - public function testSetVarOverwrites() { $view = new View($this->config, $this->viewsDir, $this->loader); @@ -49,8 +48,8 @@ class ViewTest extends \CIUnitTestCase $view = new View($this->config, $this->viewsDir, $this->loader); $expected = [ - 'foo' => 'bar', - 'bar' => 'baz' + 'foo' => 'bar', + 'bar' => 'baz' ]; $view->setData($expected); @@ -58,42 +57,38 @@ class ViewTest extends \CIUnitTestCase $this->assertEquals($expected, $view->getData()); } - //-------------------------------------------------------------------- - public function testSetDataMergesData() { $view = new View($this->config, $this->viewsDir, $this->loader); $expected = [ - 'fee' => 'fi', - 'foo' => 'bar', - 'bar' => 'baz' + 'fee' => 'fi', + 'foo' => 'bar', + 'bar' => 'baz' ]; $view->setVar('fee', 'fi'); $view->setData([ - 'foo' => 'bar', - 'bar' => 'baz' + 'foo' => 'bar', + 'bar' => 'baz' ]); $this->assertEquals($expected, $view->getData()); } - //-------------------------------------------------------------------- - public function testSetDataOverwritesData() { $view = new View($this->config, $this->viewsDir, $this->loader); $expected = [ - 'foo' => 'bar', - 'bar' => 'baz' + 'foo' => 'bar', + 'bar' => 'baz' ]; $view->setVar('foo', 'fi'); $view->setData([ - 'foo' => 'bar', - 'bar' => 'baz' + 'foo' => 'bar', + 'bar' => 'baz' ]); $this->assertEquals($expected, $view->getData()); @@ -110,21 +105,19 @@ class ViewTest extends \CIUnitTestCase $this->assertEquals(['foo' => 'bar&'], $view->getData()); } - //-------------------------------------------------------------------- - public function testSetDataWillEscapeAll() { $view = new View($this->config, $this->viewsDir, $this->loader); $expected = [ - 'foo' => 'bar&', - 'bar' => 'baz<' + 'foo' => 'bar&', + 'bar' => 'baz<' ]; $view->setData([ - 'foo' => 'bar&', - 'bar' => 'baz<' - ], 'html'); + 'foo' => 'bar&', + 'bar' => 'baz<' + ], 'html'); $this->assertEquals($expected, $view->getData()); } @@ -159,7 +152,7 @@ class ViewTest extends \CIUnitTestCase { $view = new View($this->config, $this->viewsDir, $this->loader); - $this->expectException(\CodeIgniter\Exceptions\FrameworkException::class); + $this->expectException(\CodeIgniter\View\Exceptions\ViewException::class); $view->setVar('testString', 'Hello World'); $view->render('missing'); @@ -172,7 +165,7 @@ class ViewTest extends \CIUnitTestCase $view = new View($this->config, $this->viewsDir, $this->loader); $view->setVar('testString', 'Hello World'); - $view->render('simple', null,false); + $view->render('simple', null, false); $this->assertEmpty($view->getData()); } @@ -191,8 +184,6 @@ class ViewTest extends \CIUnitTestCase $this->assertEquals($expected, $view->getData()); } - //-------------------------------------------------------------------- - public function testRenderCanSaveDataThroughConfigSetting() { $this->config->saveData = true; @@ -222,4 +213,57 @@ class ViewTest extends \CIUnitTestCase } //-------------------------------------------------------------------- + + public function testCachedRender() + { + $view = new View($this->config, $this->viewsDir, $this->loader); + + $view->setVar('testString', 'Hello World'); + $expected = '

Hello World

'; + + $this->assertContains($expected, $view->render('simple', ['cache' => 10])); + // this second renderings should go thru the cache + $this->assertContains($expected, $view->render('simple', ['cache' => 10])); + } + + //-------------------------------------------------------------------- + + public function testRenderStringSavingData() + { + $view = new View($this->config, $this->viewsDir, $this->loader); + + $view->setVar('testString', 'Hello World'); + $expected = '

Hello World

'; + $this->assertEquals($expected, $view->renderString('

', [], true)); + $this->assertArrayHasKey('testString', $view->getData()); + $this->assertEquals($expected, $view->renderString('

', [], false)); + $this->assertArrayNotHasKey('testString', $view->getData()); + } + + //-------------------------------------------------------------------- + + public function testPerformanceLogging() + { + // Make sure debugging is on for our view + $view = new View($this->config, $this->viewsDir, $this->loader, true); + $this->assertEquals(0, count($view->getPerformanceData())); + + $view->setVar('testString', 'Hello World'); + $expected = '

Hello World

'; + $this->assertEquals($expected, $view->renderString('

', [], true)); + $this->assertEquals(1, count($view->getPerformanceData())); + } + + public function testPerformanceNonLogging() + { + // Make sure debugging is on for our view + $view = new View($this->config, $this->viewsDir, $this->loader, false); + $this->assertEquals(0, count($view->getPerformanceData())); + + $view->setVar('testString', 'Hello World'); + $expected = '

Hello World

'; + $this->assertEquals($expected, $view->renderString('

', [], true)); + $this->assertEquals(0, count($view->getPerformanceData())); + } + } diff --git a/tests/system/View/Views/Simpler.php b/tests/system/View/Views/Simpler.php new file mode 100644 index 0000000000..0588b62cd1 --- /dev/null +++ b/tests/system/View/Views/Simpler.php @@ -0,0 +1 @@ +

{testString}

\ No newline at end of file