From eece160168320bb41abd1e6c6f7d192f404e8c02 Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Mon, 7 May 2018 00:03:07 -0700 Subject: [PATCH 01/21] Basic & Sessions command testing --- .gitignore | 2 + system/Commands/Sessions/CreateMigration.php | 6 ++ .../Commands/CommandsTestStreamFilter.php | 17 +++++ tests/system/Commands/CommandsTest.php | 62 ++++++++++++++++ .../system/Commands/SessionsCommandsTest.php | 70 +++++++++++++++++++ 5 files changed, 157 insertions(+) create mode 100644 tests/_support/Commands/CommandsTestStreamFilter.php create mode 100644 tests/system/Commands/CommandsTest.php create mode 100644 tests/system/Commands/SessionsCommandsTest.php diff --git a/.gitignore b/.gitignore index 809d991402..de46280a0f 100644 --- a/.gitignore +++ b/.gitignore @@ -124,3 +124,5 @@ nb-configuration.xml .vscode/ /results/ +/phpunit.xml +/application/Database/Migrations/ \ No newline at end of file diff --git a/system/Commands/Sessions/CreateMigration.php b/system/Commands/Sessions/CreateMigration.php index 18551acc5b..34cccc6238 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 { 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 @@ +<?php namespace CodeIgniter\Commands; + +class CommandsTestStreamFilter extends \php_user_filter +{ + public static $buffer = ''; + + public function filter($in, $out, &$consumed, $closing) + { + while ($bucket = stream_bucket_make_writeable($in)) { + self::$buffer .= $bucket->data; + $consumed += $bucket->datalen; + } + return PSFS_PASS_ON; + } +} + +stream_filter_register('CommandsTestStreamFilter', 'CodeIgniter\Commands\CommandsTestStreamFilter'); diff --git a/tests/system/Commands/CommandsTest.php b/tests/system/Commands/CommandsTest.php new file mode 100644 index 0000000000..c99bf43857 --- /dev/null +++ b/tests/system/Commands/CommandsTest.php @@ -0,0 +1,62 @@ +<?php namespace CodeIgniter\Commands; + +use Config\MockAppConfig; +use CodeIgniter\HTTP\UserAgent; +use CodeIgniter\CLI\CLI; +use CodeIgniter\CLI\CommandRunner; + +class CommandsTest extends \CIUnitTestCase +{ + + private $stream_filter; + + public function setUp() + { + CommandsTestStreamFilter::$buffer = ''; + $this->stream_filter = stream_filter_append(STDOUT, 'CommandsTestStreamFilter'); + + $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 = CommandsTestStreamFilter::$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 = CommandsTestStreamFilter::$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..39e792889f --- /dev/null +++ b/tests/system/Commands/SessionsCommandsTest.php @@ -0,0 +1,70 @@ +<?php namespace CodeIgniter\Commands; + +use Config\MockAppConfig; +use CodeIgniter\HTTP\UserAgent; +use CodeIgniter\CLI\CLI; +use CodeIgniter\CLI\CommandRunner; + +class SessionsCommandsTest extends \CIUnitTestCase +{ + private $stream_filter; + + public function setUp() + { + CommandsTestStreamFilter::$buffer = ''; + $this->stream_filter = stream_filter_append(STDOUT, 'CommandsTestStreamFilter'); + + $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 = CommandsTestStreamFilter::$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 = CommandsTestStreamFilter::$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); + } + + +} From 1ab2542d39c983296ac21efc8bacdd960eaac53c Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Tue, 8 May 2018 00:00:33 -0700 Subject: [PATCH 02/21] Basic command testing --- system/Commands/Server/Serve.php | 62 ++++++++++++++++--- system/Commands/Server/rewrite.php | 4 +- .../{seeds => Seeds}/CITestSeeder.php | 2 +- 3 files changed, 57 insertions(+), 11 deletions(-) rename tests/_support/Database/{seeds => Seeds}/CITestSeeder.php (96%) 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 @@ <?php namespace CodeIgniter\Commands\Server; +/** + * CodeIgniter + * + * An open source application development framework for PHP + * + * This content is released under the MIT License (MIT) + * + * Copyright (c) 2014-2018 British Columbia Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @package CodeIgniter + * @author CodeIgniter Dev Team + * @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/) + * @license https://opensource.org/licenses/MIT MIT License + * @link https://codeigniter.com + * @since Version 3.0.0 + * @filesource + */ + use CodeIgniter\CLI\BaseCommand; use CodeIgniter\CLI\CLI; +/** + * Launch the PHP development server + * + * Not testable, as it throws phpunit for a loop :-/ + * @codeCoverageIgnore + */ class Serve extends BaseCommand { - protected $group = 'CodeIgniter'; - protected $name = 'serve'; + + protected $group = 'CodeIgniter'; + protected $name = 'serve'; protected $description = 'Launchs the CodeIgniter PHP-Development Server.'; - 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"]', + 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/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 @@ -<?php +<?php namespace Tests\Support\Database\Seeds; class CITestSeeder extends \CodeIgniter\Database\Seeder { From e7e6a6be90703d00ebe550834a96c140986bf8af Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Tue, 8 May 2018 07:53:50 -0700 Subject: [PATCH 03/21] part 1 of folder renaming --- tests/_support/Database/{Seeds => seedling}/CITestSeeder.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/_support/Database/{Seeds => seedling}/CITestSeeder.php (100%) diff --git a/tests/_support/Database/Seeds/CITestSeeder.php b/tests/_support/Database/seedling/CITestSeeder.php similarity index 100% rename from tests/_support/Database/Seeds/CITestSeeder.php rename to tests/_support/Database/seedling/CITestSeeder.php From 845f46babfd7389775ec1341801a5069f23d6aba Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Tue, 8 May 2018 07:54:43 -0700 Subject: [PATCH 04/21] Part 2 of folder renaming --- tests/_support/Database/{seedling => Seeds}/CITestSeeder.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/_support/Database/{seedling => Seeds}/CITestSeeder.php (100%) diff --git a/tests/_support/Database/seedling/CITestSeeder.php b/tests/_support/Database/Seeds/CITestSeeder.php similarity index 100% rename from tests/_support/Database/seedling/CITestSeeder.php rename to tests/_support/Database/Seeds/CITestSeeder.php From 2f511fc7f83563aba4d29e0afb10d36ef3cdb259 Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Tue, 8 May 2018 07:56:56 -0700 Subject: [PATCH 05/21] Fixed my gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index de46280a0f..c3aee13314 100644 --- a/.gitignore +++ b/.gitignore @@ -125,4 +125,3 @@ nb-configuration.xml /results/ /phpunit.xml -/application/Database/Migrations/ \ No newline at end of file From c2e83e8a1b82f61691990341a449b6b5330f937f Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Fri, 25 May 2018 08:22:02 -0700 Subject: [PATCH 06/21] Flesh out View testing --- system/View/Plugins.php | 17 ++---- tests/system/View/ViewTest.php | 102 +++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 40 deletions(-) diff --git a/system/View/Plugins.php b/system/View/Plugins.php index 60e2059db8..c56408355f 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -53,7 +53,6 @@ class Plugins //-------------------------------------------------------------------- - /** * @param array $params * @@ -69,7 +68,6 @@ class Plugins //-------------------------------------------------------------------- - /** * @param array $params * @@ -89,7 +87,6 @@ class Plugins //-------------------------------------------------------------------- - /** * @param array $params * @@ -109,7 +106,6 @@ class Plugins //-------------------------------------------------------------------- - /** * @param array $params * @@ -121,7 +117,9 @@ class Plugins return lang($line, $params); } - + + //-------------------------------------------------------------------- + /** * @param array $params * @@ -129,17 +127,14 @@ class Plugins */ public static function ValidationErrors(array $params = []) { - + $validator = \config\services::validation(); - if(empty($params)) + if (empty($params)) { return $validator->listErrors(); } - - return $validator->showError($params['field']); - - + return $validator->showError($params['field']); } } diff --git a/tests/system/View/ViewTest.php b/tests/system/View/ViewTest.php index fdea5615d6..cdb27332a9 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; @@ -13,8 +14,8 @@ class ViewTest extends \CIUnitTestCase public function 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(); } //-------------------------------------------------------------------- @@ -28,8 +29,6 @@ class ViewTest extends \CIUnitTestCase $this->assertEquals(['foo' => 'bar'], $view->getData()); } - //-------------------------------------------------------------------- - public function testSetVarOverwrites() { $view = new View($this->config, $this->viewsDir, $this->loader); @@ -47,8 +46,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); @@ -56,42 +55,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()); @@ -108,21 +103,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()); } @@ -170,7 +163,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()); } @@ -189,8 +182,6 @@ class ViewTest extends \CIUnitTestCase $this->assertEquals($expected, $view->getData()); } - //-------------------------------------------------------------------- - public function testRenderCanSaveDataThroughConfigSetting() { $this->config->saveData = true; @@ -220,4 +211,57 @@ class ViewTest extends \CIUnitTestCase } //-------------------------------------------------------------------- + + public function testCachedRender() + { + $view = new View($this->config, $this->viewsDir, $this->loader); + + $view->setVar('testString', 'Hello World'); + $expected = '<h1>Hello World</h1>'; + + $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 = '<h1>Hello World</h1>'; + $this->assertEquals($expected, $view->renderString('<h1><?= $testString ?></h1>', [], true)); + $this->assertArrayHasKey('testString', $view->getData()); + $this->assertEquals($expected, $view->renderString('<h1><?= $testString ?></h1>', [], 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 = '<h1>Hello World</h1>'; + $this->assertEquals($expected, $view->renderString('<h1><?= $testString ?></h1>', [], 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 = '<h1>Hello World</h1>'; + $this->assertEquals($expected, $view->renderString('<h1><?= $testString ?></h1>', [], true)); + $this->assertEquals(0, count($view->getPerformanceData())); + } + } From a56adf9f509aa0b01de0933b8e68a3b663aeebe7 Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Fri, 25 May 2018 23:38:31 -0700 Subject: [PATCH 07/21] Parser testing --- system/Exceptions/FrameworkException.php | 12 +- system/View/Parser.php | 32 +- tests/_support/View/Views/simpler.php | 1 + tests/system/View/ParserTest.php | 401 +++++++++++++++-------- tests/system/View/ViewTest.php | 2 +- tests/system/View/Views/Simpler.php | 1 + 6 files changed, 284 insertions(+), 165 deletions(-) create mode 100644 tests/_support/View/Views/simpler.php create mode 100644 tests/system/View/Views/Simpler.php diff --git a/system/Exceptions/FrameworkException.php b/system/Exceptions/FrameworkException.php index 8dd95a4ab3..76646ee3eb 100644 --- a/system/Exceptions/FrameworkException.php +++ b/system/Exceptions/FrameworkException.php @@ -10,28 +10,30 @@ */ class FrameworkException extends \RuntimeException implements ExceptionInterface { + public static function forEmptyBaseURL(): self { - return new self('You have an empty or invalid base URL. The baseURL value must be set in Config\App.php, or through the .env file.'); + 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.'); } public static function forInvalidFile(string $path) { - return new self(lang('Core.invalidFile', [$path])); + return new static(lang('Core.invalidFile', [$path])); } public static function forCopyError() { - return new self(lang('Core.copyError')); + return new static(lang('Core.copyError')); } public static function forMissingExtension(string $extension) { - return new self(lang('Core.missingExtension', [$extension])); + return new static(lang('Core.missingExtension', [$extension])); } public static function forNoHandlers(string $class) { - return new self(lang('Core.noHandlers', [$class])); + return new static(lang('Core.noHandlers', [$class])); } + } diff --git a/system/View/Parser.php b/system/View/Parser.php index b029e9d376..bb7036904a 100644 --- a/system/View/Parser.php +++ b/system/View/Parser.php @@ -298,24 +298,26 @@ 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; +// } //-------------------------------------------------------------------- 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 @@ +<h1>{testString}</h1> \ No newline at end of file diff --git a/tests/system/View/ParserTest.php b/tests/system/View/ParserTest.php index 82968051e3..18b5d2214a 100644 --- a/tests/system/View/ParserTest.php +++ b/tests/system/View/ParserTest.php @@ -1,15 +1,16 @@ <?php use CodeIgniter\View\Parser; +use CodeIgniter\View\Exceptions\ViewException; class ParserTest extends \CIUnitTestCase { public function setUp() { - $this->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(); } // -------------------------------------------------------------------- @@ -53,9 +54,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}"; @@ -71,14 +72,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)); @@ -89,10 +90,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}"; @@ -113,26 +114,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'], ], @@ -144,13 +145,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'], @@ -169,15 +209,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)); @@ -188,15 +228,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'], @@ -243,6 +283,8 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('http%3A%2F%2Ffoo.com', $parser->renderString($template)); } + //-------------------------------------------------------------------- + public function testFilterWithNoArgument() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); @@ -257,8 +299,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); @@ -282,7 +322,7 @@ class ParserTest extends \CIUnitTestCase $parser = new Parser($this->config, $this->viewsDir, $this->loader); $data = [ - 'title' => '<script>Heroes</script>', + 'title' => '<script>Heroes</script>', 'powers' => [ ['link' => "<a href='test'>Link</a>"], ], @@ -293,35 +333,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' => '<script>Heroes</script>', + ]; - $data = [ - 'title' => '<script>Heroes</script>', - ]; - - $template = "{! title!}"; - $parser->setData($data); - $this->assertEquals('<script>Heroes</script>', $parser->renderString($template)); - } + $template = "{! title!}"; + $parser->setData($data); + $this->assertEquals('<script>Heroes</script>', $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)); @@ -332,15 +370,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)); @@ -351,9 +389,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 }"; @@ -362,12 +400,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, ]; @@ -377,12 +413,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, ]; @@ -392,14 +426,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 }"; @@ -408,6 +440,22 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('Welcome', $parser->renderString($template)); } + public function testBadConditional() + { + $this->expectException(ViewException::class); + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $data = [ + 'doit' => true, + 'dontdoit' => false + ]; + + $template = "{if doit}achoo 'howdy'{endif}"; + $parser->setData($data); + + $result = $parser->renderString($template); + echo var_dump($result); + } + //-------------------------------------------------------------------- public function testWontParsePHP() @@ -423,9 +471,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 }"; @@ -438,75 +486,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 @@ -514,15 +564,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; @@ -541,7 +591,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); @@ -550,15 +600,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); @@ -567,15 +615,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); @@ -584,15 +630,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) @@ -616,7 +660,7 @@ class ParserTest extends \CIUnitTestCase public function testParseLoopWithDollarSign() { $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ + $data = [ 'books' => [ ['price' => '12.50'], ], @@ -628,5 +672,74 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals("<p>Price $: 12.50</p>", $parser->renderString($template)); } - // -------------------------------------------------------------------- + //-------------------------------------------------------------------- + + public function testCachedRender() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setVar('teststring', 'Hello World'); + + $expected = '<h1>Hello World</h1>'; + $this->assertEquals($expected, $parser->render('template1', ['cache' => 10])); + // this second renderings should go thru the cache + $this->assertEquals($expected, $parser->render('template1', ['cache' => 10])); + } + + //-------------------------------------------------------------------- + + public function testRenderFindsView() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['testString' => 'Hello World']); + + $expected = '<h1>Hello World</h1>'; + $this->assertEquals($expected, $parser->render('Simpler')); + } + + public function testRenderSearchesForView() + { + $_SERVER['HTTP_HOST'] = 'example.com'; + $_GET = []; + $this->config = new \Config\Pager(); + $this->pager = new \CodeIgniter\Pager\Pager($this->config, \Config\Services::parser()); + $this->assertTrue(strpos($this->pager->links(), '<ul class="pagination">') > 0); + } + + public function testRenderCantFindView() + { + $this->expectException(ViewException::class); + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['testString' => 'Hello World']); + + $expected = '<h1>Hello World</h1>'; + $result = $parser->render('Simplest'); + } + + //-------------------------------------------------------------------- + + public function testRenderSavingData() + { + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser->setData(['testString' => 'Hello World']); + + $expected = '<h1>Hello World</h1>'; + $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 = '<h1>Hello World</h1>'; + $pattern = '<h1>{testString}</h1>'; + $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/ViewTest.php b/tests/system/View/ViewTest.php index cdb27332a9..68b33373e0 100644 --- a/tests/system/View/ViewTest.php +++ b/tests/system/View/ViewTest.php @@ -150,7 +150,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'); 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 @@ +<h1>{testString}</h1> \ No newline at end of file From 0ab579ee8827c7b16b3efd12fbe5231c1d5ca6bb Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Sun, 27 May 2018 00:12:39 -0700 Subject: [PATCH 08/21] Parser tests --- system/View/Parser.php | 1 + tests/system/View/ParserTest.php | 16 ---------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/system/View/Parser.php b/system/View/Parser.php index bb7036904a..89f7dd7bd0 100644 --- a/system/View/Parser.php +++ b/system/View/Parser.php @@ -528,6 +528,7 @@ class Parser extends View extract($this->data); $result = eval('?>' . $template . '<?php '); + //TODO under what circumstances would we ever get a FALSE? Could not induce one if ($result === false) { throw ViewException::forTagSyntaxError(str_replace(['?>', '<?php '], '', $template)); diff --git a/tests/system/View/ParserTest.php b/tests/system/View/ParserTest.php index 18b5d2214a..fd4dcaff79 100644 --- a/tests/system/View/ParserTest.php +++ b/tests/system/View/ParserTest.php @@ -440,22 +440,6 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals('Welcome', $parser->renderString($template)); } - public function testBadConditional() - { - $this->expectException(ViewException::class); - $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $data = [ - 'doit' => true, - 'dontdoit' => false - ]; - - $template = "{if doit}achoo 'howdy'{endif}"; - $parser->setData($data); - - $result = $parser->renderString($template); - echo var_dump($result); - } - //-------------------------------------------------------------------- public function testWontParsePHP() From ac6ec0035442c7d36c6f2f8459bf468bbc8615ad Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Mon, 4 Jun 2018 01:21:21 -0700 Subject: [PATCH 09/21] Flesh out Parser tests; handle ParseError --- system/View/Parser.php | 16 +++---- tests/system/View/ParserTest.php | 73 +++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/system/View/Parser.php b/system/View/Parser.php index 89f7dd7bd0..069ca1733d 100644 --- a/system/View/Parser.php +++ b/system/View/Parser.php @@ -297,15 +297,12 @@ class Parser extends View } //-------------------------------------------------------------------- - //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); // } - //-------------------------------------------------------------------- - //FIXME the following method does not appear to be used anywhere, so commented out // function strpos_all($haystack, $needle) // { @@ -318,7 +315,6 @@ class Parser extends View // } // return $allpos; // } - //-------------------------------------------------------------------- /** @@ -526,14 +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 . '<?php '); - - //TODO under what circumstances would we ever get a FALSE? Could not induce one - if ($result === false) + try { + $result = eval('?>' . $template . '<?php '); + } catch (\ParseError $e) + { + ob_end_clean(); throw ViewException::forTagSyntaxError(str_replace(['?>', '<?php '], '', $template)); } - return ob_get_clean(); } @@ -653,7 +649,7 @@ class Parser extends View $escape = false; } // If no `esc` filter is found, then we'll need to add one. - elseif ( ! preg_match('/^|\s+esc/', $key)) + elseif ( ! preg_match('/\s+esc/', $key)) { $escape = 'html'; } diff --git a/tests/system/View/ParserTest.php b/tests/system/View/ParserTest.php index 3b5faf0567..7e0dadb12b 100644 --- a/tests/system/View/ParserTest.php +++ b/tests/system/View/ParserTest.php @@ -10,9 +10,9 @@ class ParserTest extends \CIUnitTestCase { parent::setUp(); - $this->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(); } // -------------------------------------------------------------------- @@ -173,11 +173,11 @@ class ParserTest extends \CIUnitTestCase $eagle->home = 'Rockies'; $data = [ 'birds' => [[ - 'pop' => $eagle, - 'mom' => 'Owl', - 'kids' => ['Tom', 'Dick', 'Harry'], - 'home' => opendir('.'), - ]], + 'pop' => $eagle, + 'mom' => 'Owl', + 'kids' => ['Tom', 'Dick', 'Harry'], + 'home' => opendir('.'), + ]], ]; $template = "{ birds }{mom} and {pop} work at {home}{/birds}"; @@ -285,6 +285,32 @@ 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() @@ -444,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); @@ -666,9 +710,9 @@ class ParserTest extends \CIUnitTestCase $parser->setVar('teststring', 'Hello World'); $expected = '<h1>Hello World</h1>'; - $this->assertEquals($expected, $parser->render('template1', ['cache' => 10])); + $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])); + $this->assertEquals($expected, $parser->render('template1', ['cache' => 10, 'cache_name' => 'HelloWorld'])); } //-------------------------------------------------------------------- @@ -682,15 +726,6 @@ class ParserTest extends \CIUnitTestCase $this->assertEquals($expected, $parser->render('Simpler')); } - public function testRenderSearchesForView() - { - $_SERVER['HTTP_HOST'] = 'example.com'; - $_GET = []; - $this->config = new \Config\Pager(); - $this->pager = new \CodeIgniter\Pager\Pager($this->config, \Config\Services::parser()); - $this->assertTrue(strpos($this->pager->links(), '<ul class="pagination">') > 0); - } - public function testRenderCantFindView() { $this->expectException(ViewException::class); From a7e3c559b2ceaa25432463d32e3c11f08feff8ac Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Mon, 4 Jun 2018 07:53:18 -0700 Subject: [PATCH 10/21] Flesh out Filter testing --- tests/system/View/ParserFilterTest.php | 37 ++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) 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 <mark>jumped over</mark> 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 = <<<EOF +<code><span style="color: #000000"> +<span style="color: #0000BB">Sincerely </span> +</span> +</code> +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 = '<p>Sincerely\nMe</p>'; + $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)); } //-------------------------------------------------------------------- From f5a7fbf72bccd92b0bc8a3324efbe9dfdf21957e Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Tue, 5 Jun 2018 12:48:18 -0700 Subject: [PATCH 11/21] Flesh out Cell & Plugins testing --- system/View/Cell.php | 16 ++-- system/View/Plugins.php | 12 +++ tests/system/View/CellTest.php | 117 +++++++++++++++++++++---- tests/system/View/ParserPluginTest.php | 1 + tests/system/View/SampleClass.php | 9 +- 5 files changed, 129 insertions(+), 26 deletions(-) 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/Plugins.php b/system/View/Plugins.php index c56408355f..97f9209221 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -46,7 +46,10 @@ class Plugins public static function currentURL(array $params = []) { if ( ! function_exists('current_url')) + // can't unit test this since it is loaded in CIUnitTestCase setup + // @codeCoverageIgnoreStart helper('url'); + // @codeCoverageIgnoreEnd return current_url(); } @@ -61,7 +64,10 @@ class Plugins public static function previousURL(array $params = []) { if ( ! function_exists('previous_url')) + // can't unit test this since it is loaded in CIUnitTestCase setup + // @codeCoverageIgnoreStart helper('url'); + // @codeCoverageIgnoreEnd return previous_url(); } @@ -76,7 +82,10 @@ class Plugins public static function mailto(array $params = []) { if ( ! function_exists('mailto')) + // can't unit test this since it is loaded in CIUnitTestCase setup + // @codeCoverageIgnoreStart helper('url'); + // @codeCoverageIgnoreEnd $email = $params['email'] ?? ''; $title = $params['title'] ?? ''; @@ -95,7 +104,10 @@ class Plugins public static function safeMailto(array $params = []) { if ( ! function_exists('safe_mailto')) + // can't unit test this since it is loaded in CIUnitTestCase setup + // @codeCoverageIgnoreStart helper('url'); + // @codeCoverageIgnoreEnd $email = $params['email'] ?? ''; $title = $params['title'] ?? ''; 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 @@ <?php use CodeIgniter\View\Cell; +use CodeIgniter\View\Exceptions\ViewException; use Tests\Support\Cache\Handlers\MockHandler; -include_once __DIR__ .'/SampleClass.php'; +include_once __DIR__ . '/SampleClass.php'; class CellTest extends \CIUnitTestCase { + protected $cache; /** @@ -21,28 +23,28 @@ class CellTest extends \CIUnitTestCase parent::setUp(); $this->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/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 @@ <?php use CodeIgniter\View\Parser; +use CodeIgniter\View\Plugins; class ParserPluginTest extends \CIUnitTestCase { 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 From 2ac3d164ad28f3ec410fe2019e08df166eae1e7a Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Tue, 5 Jun 2018 22:17:44 -0700 Subject: [PATCH 12/21] Modify gitignore to drop generated migrations --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c3aee13314..32c14d01b5 100644 --- a/.gitignore +++ b/.gitignore @@ -63,6 +63,8 @@ writable/uploads/* writable/debugbar/* +application/Database/Migrations/2* + php_errors.log #------------------------- From aa23b0eb739e92c694a0609f269d11b97a47d5e6 Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Wed, 6 Jun 2018 07:32:26 -0700 Subject: [PATCH 13/21] Use the proper test stream filter --- tests/system/Commands/CommandsTest.php | 11 ++++++----- tests/system/Commands/SessionsCommandsTest.php | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/system/Commands/CommandsTest.php b/tests/system/Commands/CommandsTest.php index c99bf43857..00dd6439d6 100644 --- a/tests/system/Commands/CommandsTest.php +++ b/tests/system/Commands/CommandsTest.php @@ -1,9 +1,10 @@ <?php namespace CodeIgniter\Commands; -use Config\MockAppConfig; +use Tests\Support\Config\MockAppConfig; use CodeIgniter\HTTP\UserAgent; use CodeIgniter\CLI\CLI; use CodeIgniter\CLI\CommandRunner; +use CodeIgniter\Test\Filters\CITestStreamFilter; class CommandsTest extends \CIUnitTestCase { @@ -12,8 +13,8 @@ class CommandsTest extends \CIUnitTestCase public function setUp() { - CommandsTestStreamFilter::$buffer = ''; - $this->stream_filter = stream_filter_append(STDOUT, 'CommandsTestStreamFilter'); + CITestStreamFilter::$buffer = ''; + $this->stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter'); $this->env = new \CodeIgniter\Config\DotEnv(ROOTPATH); $this->env->load(); @@ -42,7 +43,7 @@ class CommandsTest extends \CIUnitTestCase public function testHelpCommand() { $this->runner->index(['help']); - $result = CommandsTestStreamFilter::$buffer; + $result = CITestStreamFilter::$buffer; // make sure the result looks like a command list $this->assertContains('Displays basic usage information.', $result); @@ -52,7 +53,7 @@ class CommandsTest extends \CIUnitTestCase public function testListCommands() { $this->runner->index(['list']); - $result = CommandsTestStreamFilter::$buffer; + $result = CITestStreamFilter::$buffer; // make sure the result looks like a command list $this->assertContains('Lists the available commands.', $result); diff --git a/tests/system/Commands/SessionsCommandsTest.php b/tests/system/Commands/SessionsCommandsTest.php index 39e792889f..7171f8e8ad 100644 --- a/tests/system/Commands/SessionsCommandsTest.php +++ b/tests/system/Commands/SessionsCommandsTest.php @@ -1,9 +1,10 @@ <?php namespace CodeIgniter\Commands; -use Config\MockAppConfig; +use Tests\Support\Config\MockAppConfig; use CodeIgniter\HTTP\UserAgent; use CodeIgniter\CLI\CLI; use CodeIgniter\CLI\CommandRunner; +use CodeIgniter\Test\Filters\CITestStreamFilter; class SessionsCommandsTest extends \CIUnitTestCase { @@ -11,8 +12,8 @@ class SessionsCommandsTest extends \CIUnitTestCase public function setUp() { - CommandsTestStreamFilter::$buffer = ''; - $this->stream_filter = stream_filter_append(STDOUT, 'CommandsTestStreamFilter'); + CITestStreamFilter::$buffer = ''; + $this->stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter'); $this->env = new \CodeIgniter\Config\DotEnv(ROOTPATH); $this->env->load(); @@ -41,7 +42,7 @@ class SessionsCommandsTest extends \CIUnitTestCase public function testCreateMigrationCommand() { $this->runner->index(['session:migration']); - $result = CommandsTestStreamFilter::$buffer; + $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 @@ -58,7 +59,7 @@ class SessionsCommandsTest extends \CIUnitTestCase CLI::init(); $this->runner->index(['session:migration']); - $result = CommandsTestStreamFilter::$buffer; + $result = CITestStreamFilter::$buffer; // make sure we end up with a migration class in the right place $this->assertContains('Created file:', $result); From 30fba9ccdd7023a109fd145d4c8e19b392bb4ae9 Mon Sep 17 00:00:00 2001 From: Lonnie Ezell <lonnieje@gmail.com> Date: Wed, 6 Jun 2018 22:09:15 -0500 Subject: [PATCH 14/21] Don't allow failures for php 7.2 on Travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) 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: From b29efcb12c17133f4b917ce13748c29a97656928 Mon Sep 17 00:00:00 2001 From: Lonnie Ezell <lonnieje@gmail.com> Date: Wed, 6 Jun 2018 22:17:15 -0500 Subject: [PATCH 15/21] Rearranging phpunit whitelist to try and appease Travis. --- phpunit.xml.dist | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 @@ <whitelist processUncoveredFilesFromWhitelist="true"> <directory suffix=".php">./system</directory> <exclude> - <file>./system/bootstrap.php</file> - <file>./system/Commands/Sessions/Views/migration.tpl.php</file> - <file>./system/ComposerScripts.php</file> - <file>./system/Config/Routes.php</file> <directory>./system/Debug/Toolbar/Views</directory> <directory>./system/Pager/Views</directory> <directory>./system/ThirdParty</directory> <directory>./system/Validation/Views</directory> + <file>./system/bootstrap.php</file> + <file>./system/Commands/Sessions/Views/migration.tpl.php</file> + <file>./system/ComposerScripts.php</file> + <file>./system/Config/Routes.php</file> </exclude> </whitelist> </filter> From fc9add0305d9749beb58feac466860918f6e96c6 Mon Sep 17 00:00:00 2001 From: Lonnie Ezell <lonnieje@gmail.com> Date: Wed, 6 Jun 2018 22:56:26 -0500 Subject: [PATCH 16/21] Provide a simpler default value for session table name. --- system/Commands/Sessions/CreateMigration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Commands/Sessions/CreateMigration.php b/system/Commands/Sessions/CreateMigration.php index 34cccc6238..5c9427e067 100644 --- a/system/Commands/Sessions/CreateMigration.php +++ b/system/Commands/Sessions/CreateMigration.php @@ -104,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'; From bfc73e43104f91bad311e047f504119c1853effc Mon Sep 17 00:00:00 2001 From: Lonnie Ezell <lonnieje@gmail.com> Date: Wed, 6 Jun 2018 22:56:52 -0500 Subject: [PATCH 17/21] Fix an issue with non-namespaced seeder. --- tests/system/Database/Live/AliasTest.php | 2 +- tests/system/Database/Live/CIDbTestCaseTest.php | 2 +- tests/system/Database/Live/CountTest.php | 2 +- tests/system/Database/Live/DeleteTest.php | 2 +- tests/system/Database/Live/EmptyTest.php | 2 +- tests/system/Database/Live/ForgeTest.php | 2 +- tests/system/Database/Live/FromTest.php | 2 +- tests/system/Database/Live/GetTest.php | 2 +- tests/system/Database/Live/GroupTest.php | 2 +- tests/system/Database/Live/IncrementTest.php | 2 +- tests/system/Database/Live/InsertTest.php | 2 +- tests/system/Database/Live/JoinTest.php | 2 +- tests/system/Database/Live/LikeTest.php | 2 +- tests/system/Database/Live/LimitTest.php | 2 +- tests/system/Database/Live/ModelTest.php | 2 +- tests/system/Database/Live/OrderTest.php | 2 +- tests/system/Database/Live/PreparedQueryTest.php | 2 +- tests/system/Database/Live/SelectTest.php | 2 +- tests/system/Database/Live/UpdateTest.php | 2 +- tests/system/Database/Live/WhereTest.php | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) 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() { From 4f13dff1f0e75d64ec1e6cffac35a74bda1cd8de Mon Sep 17 00:00:00 2001 From: Lonnie Ezell <lonnieje@gmail.com> Date: Wed, 6 Jun 2018 22:57:27 -0500 Subject: [PATCH 18/21] Safety so seeders don't get loaded multiple times. --- system/Database/Seeder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); From 2d5be738200159fc843f5494ffda23e9762ac568 Mon Sep 17 00:00:00 2001 From: Lonnie Ezell <lonnieje@gmail.com> Date: Wed, 6 Jun 2018 22:58:29 -0500 Subject: [PATCH 19/21] Cannot unpack arrays with string keys. Fixes #1057 --- system/HTTP/Response.php | 3 +++ system/Helpers/cookie_helper.php | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) 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); } } From fa64b01f56e8f6b88c9061d05cc02f692cd3c8e4 Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Thu, 7 Jun 2018 02:56:46 -0700 Subject: [PATCH 20/21] Flesh out Common tests - part 1 --- tests/_support/View/Views/simple.php | 1 + tests/system/CommonFunctionsTest.php | 168 ++++++++++++++++++++++++--- 2 files changed, 151 insertions(+), 18 deletions(-) create mode 100644 tests/_support/View/Views/simple.php diff --git a/tests/_support/View/Views/simple.php b/tests/_support/View/Views/simple.php new file mode 100644 index 0000000000..afd6c25fe2 --- /dev/null +++ b/tests/_support/View/Views/simple.php @@ -0,0 +1 @@ +<h1><?= $testString ?></h1> \ No newline at end of file diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index e5ac5b327c..7c334120fa 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -1,5 +1,8 @@ <?php +use Tests\Support\Autoloader\MockFileLocator; +use CodeIgniter\Router\RouteCollection; + /** * @backupGlobals enabled */ @@ -12,7 +15,7 @@ class CommomFunctionsTest extends \CIUnitTestCase { parent::setUp(); - unset($_ENV['foo'], $_SERVER['foo']); + unset($_ENV['foo'], $_SERVER['foo']); } //-------------------------------------------------------------------- @@ -48,40 +51,169 @@ class CommomFunctionsTest extends \CIUnitTestCase // ------------------------------------------------------------------------ - public function testEnvReturnsDefault() - { - $this->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 testView() + { + $data = [ + 'testString' => 'bar', + 'bar' => 'baz', + ]; + $expected = '<h1>bar</h1>'; + $this->assertContains($expected, view('\Tests\Support\View\Views\simple', $data, [])); + } + + public function testViewSavedData() + { + $data = [ + 'testString' => 'bar', + 'bar' => 'baz', + ]; + $expected = '<h1>bar</h1>'; + $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('<input type="hidden" ', csrf_field()); + } } From 94bce7c873e4930c6e2f8c52a8fff60278cb8d6d Mon Sep 17 00:00:00 2001 From: Master Yoda <jim_parry@bcit.ca> Date: Thu, 7 Jun 2018 20:50:03 -0700 Subject: [PATCH 21/21] Part 2 of expanded common function testing --- system/Common.php | 11 +++++ tests/system/CommonFunctionsTest.php | 61 +++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 1 deletion(-) 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/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index 7c334120fa..0c88d29c25 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -1,7 +1,15 @@ <?php -use Tests\Support\Autoloader\MockFileLocator; +use Config\App; +use Config\Autoload; +use CodeIgniter\Config\Services; use CodeIgniter\Router\RouteCollection; +use CodeIgniter\HTTP\RequestResponse; +use CodeIgniter\HTTP\RedirectResponse; +use CodeIgniter\HTTP\URI; +use CodeIgniter\HTTP\UserAgent; +use Tests\Support\Autoloader\MockFileLocator; +use Tests\Support\HTTP\MockIncomingRequest; /** * @backupGlobals enabled @@ -102,6 +110,11 @@ class CommomFunctionsTest extends \CIUnitTestCase $this->assertInstanceOf(\CodeIgniter\HTTP\RedirectResponse::class, redirect('base')); } + public function testRedirectDefault() + { + $this->assertInstanceOf(\CodeIgniter\HTTP\RedirectResponse::class, redirect()); + } + // ------------------------------------------------------------------------ public function testView() @@ -216,4 +229,50 @@ class CommomFunctionsTest extends \CIUnitTestCase $this->assertContains('<input type="hidden" ', csrf_field()); } + // ------------------------------------------------------------------------ + + public function testOldInput() + { + // setup from RedirectResponseTest... + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $this->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 + } + }