From 240eddeff32480aa4db548dbe179e4ed77ee124e Mon Sep 17 00:00:00 2001 From: Karoly Gossler Date: Fri, 17 Feb 2023 00:31:29 +0100 Subject: [PATCH 1/4] add(test) enable phpunit tests --- .github/workflows/continuous-integration.yml | 5 +++- .gitignore | 3 +++ composer.json | 12 ++++++++- phpunit.xml.dist | 27 ++++++++++++++++++++ tests/bootstrap.php | 15 +++++++++++ 5 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 phpunit.xml.dist create mode 100644 tests/bootstrap.php diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 3839fbaa0..8a92a2094 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -58,5 +58,8 @@ jobs: - name: Run Check configuration run: php data/bin/check_configuration.php - - name: Run Tests + - name: Run Lime Tests run: php data/bin/symfony symfony:test --trace + + - name: Run PHPUnit Tests + run: php vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index 3c17d4767..0644b20d6 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ lib/plugins/sfDoctrinePlugin/test/functional/fixtures/log/ /vendor /composer.lock .php-cs-fixer.cache +.phpunit.result.cache +phpunit.xml +/tests/fixtures/symfony/log diff --git a/composer.json b/composer.json index 096711cad..61b1397b6 100755 --- a/composer.json +++ b/composer.json @@ -8,7 +8,9 @@ "swiftmailer/swiftmailer": "^5.2 || ^6.0" }, "require-dev": { - "psr/log": "*" + "psr/log": "*", + "phpunit/phpunit": "^9.6", + "symfony/phpunit-bridge": "^7.0" }, "autoload": { "files": ["autoload.php"] @@ -26,5 +28,13 @@ "replace": { "lexpress/symfony1": "^1.5" }, + "scripts": { + "test": [ + "@test:lime", + "@test:phpunit" + ], + "test:lime": "php data/bin/symfony symfony:test --trace", + "test:phpunit": "phpunit" + }, "bin": ["data/bin/symfony"] } diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 000000000..99dc45452 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,27 @@ + + + + + + + + + + + + ./tests/ + + + + + + ./lib/ + + + diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 000000000..f362d1471 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bridge\PhpUnit\DeprecationErrorHandler; + +if ('disabled' !== getenv('SYMFONY_DEPRECATIONS_HELPER')) { + DeprecationErrorHandler::register(getenv('SYMFONY_DEPRECATIONS_HELPER')); +} From c490f3551d202a8e5d5b4ebf2ce7e42d0b9b665b Mon Sep 17 00:00:00 2001 From: Karoly Gossler Date: Fri, 16 Feb 2024 08:28:35 +0100 Subject: [PATCH 2/4] add(test) port of sfComponentText unit test --- tests/action/sfComponentTest.php | 77 ++++++++++++++ tests/fixtures/myComponent.php | 8 ++ tests/fixtures/myEventDispatcherTest.php | 14 +++ tests/sfContext.class.php | 123 +++++++++++++++++++++++ tests/sfEventDispatcherTestCase.php | 39 +++++++ tests/sfNoRouting.class.php | 107 ++++++++++++++++++++ tests/sfParameterHolderProxyTestCase.php | 54 ++++++++++ 7 files changed, 422 insertions(+) create mode 100644 tests/action/sfComponentTest.php create mode 100644 tests/fixtures/myComponent.php create mode 100644 tests/fixtures/myEventDispatcherTest.php create mode 100644 tests/sfContext.class.php create mode 100644 tests/sfEventDispatcherTestCase.php create mode 100644 tests/sfNoRouting.class.php create mode 100644 tests/sfParameterHolderProxyTestCase.php diff --git a/tests/action/sfComponentTest.php b/tests/action/sfComponentTest.php new file mode 100644 index 000000000..91e695b50 --- /dev/null +++ b/tests/action/sfComponentTest.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require_once __DIR__.'/../fixtures/myComponent.php'; +require_once __DIR__.'/../sfContext.class.php'; +require_once __DIR__.'/../sfNoRouting.class.php'; +require_once __DIR__.'/../sfEventDispatcherTestCase.php'; + +/** + * @internal + * + * @coversNothing + */ +class sfComponentTest extends sfEventDispatcherTestCase +{ + private sfContext $context; + + public function setUp(): void + { + $this->context = sfContext::getInstance(array( + 'routing' => 'sfNoRouting', + 'request' => 'sfWebRequest', + )); + + $this->testObject = new myComponent($this->context, 'module', 'action'); + $this->dispatcher = $this->context->getEventDispatcher(); + $this->class = 'component'; + } + + public function testInitialize() + { + $component = new myComponent($this->context, 'module', 'action'); + $this->assertSame($this->context, $component->getContext(), '->initialize() takes a sfContext object as its first argument'); + $component->initialize($this->context, 'module', 'action'); + $this->assertSame($this->context, $component->getContext(), '->initialize() takes a sfContext object as its first argument'); + } + + public function testGetContext() + { + $component = new myComponent($this->context, 'module', 'action'); + + $component->initialize($this->context, 'module', 'action'); + $this->assertSame($this->context, $component->getContext(), '->getContext() returns the current context'); + } + + public function testGetRequest() + { + $component = new myComponent($this->context, 'module', 'action'); + + $component->initialize($this->context, 'module', 'action'); + $this->assertSame($this->context->getRequest(), $component->getRequest(), '->getRequest() returns the current request'); + } + + public function testGetResponse() + { + $component = new myComponent($this->context, 'module', 'action'); + + $component->initialize($this->context, 'module', 'action'); + $this->assertSame($this->context->getResponse(), $component->getResponse(), '->getResponse() returns the current response'); + } + + public function testSetter() + { + $component = new myComponent($this->context, 'module', 'action'); + + $component->foo = array(); + $component->foo[] = 'bar'; + $this->assertSame(array('bar'), $component->foo, '__set() populates component variables'); + } +} diff --git a/tests/fixtures/myComponent.php b/tests/fixtures/myComponent.php new file mode 100644 index 000000000..008695803 --- /dev/null +++ b/tests/fixtures/myComponent.php @@ -0,0 +1,8 @@ +setReturnValue($arguments[0]); + + return true; + } + } +} diff --git a/tests/sfContext.class.php b/tests/sfContext.class.php new file mode 100644 index 000000000..8fead9ad3 --- /dev/null +++ b/tests/sfContext.class.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +class sfContext +{ + protected static ?sfContext $instance = null; + + public $configuration; + public $request; + public $response; + public $controller; + public $routing; + public $user; + public $storage; + + protected string $sessionPath = ''; + + protected sfEventDispatcher $dispatcher; + + public static function getInstance($factories = array(), $force = false): self + { + if (!isset(self::$instance) || $force) { + self::$instance = new sfContext(); + + self::$instance->sessionPath = sys_get_temp_dir().'/sessions_'.rand(11111, 99999); + self::$instance->storage = new sfSessionTestStorage(array('session_path' => self::$instance->sessionPath)); + + self::$instance->dispatcher = new sfEventDispatcher(); + + foreach ($factories as $type => $class) { + self::$instance->inject($type, $class); + } + } + + return self::$instance; + } + + public function __destruct() + { + sfToolkit::clearDirectory($this->sessionPath); + } + + public static function hasInstance()/*: true*/ + { + return true; + } + + public function getEventDispatcher(): sfEventDispatcher + { + return self::$instance->dispatcher; + } + + public function getModuleName(): string + { + return 'module'; + } + + public function getActionName(): string + { + return 'action'; + } + + public function getConfiguration() + { + return $this->configuration; + } + + public function getRequest() + { + return $this->request; + } + + public function getResponse() + { + return $this->response; + } + + public function getRouting() + { + return $this->routing; + } + + public function getStorage() + { + return $this->storage; + } + + public function getUser() + { + return $this->user; + } + + public function getController() + { + return $this->controller; + } + + public function inject($type, $class, $parameters = array()) + { + switch ($type) { + case 'routing': + $object = new $class($this->dispatcher, null, $parameters); + break; + case 'response': + $object = new $class($this->dispatcher, $parameters); + break; + case 'request': + $object = new $class($this->dispatcher, $this->routing, $parameters); + break; + default: + $object = new $class($this, $parameters); + } + + $this->{$type} = $object; + } +} diff --git a/tests/sfEventDispatcherTestCase.php b/tests/sfEventDispatcherTestCase.php new file mode 100644 index 000000000..3136fc4f9 --- /dev/null +++ b/tests/sfEventDispatcherTestCase.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use PHPUnit\Framework\TestCase; + +require_once __DIR__.'/fixtures/myEventDispatcherTest.php'; + +/** + * @internal + * + * @coversNothing + */ +class sfEventDispatcherTestCase extends TestCase +{ + protected $testObject; + protected $dispatcher; + protected $class; + + public function testExistedMethod() + { + $this->dispatcher->connect($this->class.'.method_not_found', array(myEventDispatcherTest::class, 'newMethod')); + + $this->assertSame('ok', $this->testObject->newMethod('ok'), '__call() accepts new methods via sfEventDispatcher'); + } + + public function testNonExistantMethod() + { + $this->expectException(sfException::class); + + $this->testObject->nonexistantmethodname(); + } +} diff --git a/tests/sfNoRouting.class.php b/tests/sfNoRouting.class.php new file mode 100644 index 000000000..23b8a5942 --- /dev/null +++ b/tests/sfNoRouting.class.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * sfNoRouting class is a very simple routing class that uses GET parameters. + * + * @author Fabien Potencier + * + * @version SVN: $Id: sfNoRouting.class.php 20566 2009-07-29 07:04:01Z fabien $ + */ +class sfNoRouting extends sfRouting +{ + /** + * @see sfRouting + */ + public function getCurrentInternalUri($with_route_name = false) + { + $parameters = $this->mergeArrays($this->defaultParameters, $_GET); + $action = sprintf('%s/%s', $parameters['module'], $parameters['action']); + + // other parameters + unset($parameters['module'], $parameters['action']); + ksort($parameters); + $parameters = count($parameters) ? '?'.http_build_query($parameters, '', '&') : ''; + + return sprintf('%s%s', $action, $parameters); + } + + /** + * @see sfRouting + */ + public function generate($name, $params = array(), $absolute = false) + { + $parameters = $this->mergeArrays($this->defaultParameters, $params); + if ($this->getDefaultParameter('module') == $parameters['module']) { + unset($parameters['module']); + } + if ($this->getDefaultParameter('action') == $parameters['action']) { + unset($parameters['action']); + } + + $parameters = http_build_query($parameters, '', '&'); + + return $this->fixGeneratedUrl('/'.($parameters ? '?'.$parameters : ''), $absolute); + } + + /** + * @see sfRouting + */ + public function parse($url) + { + return array(); + } + + /** + * @see sfRouting + */ + public function getRoutes() + { + return array(); + } + + /** + * @see sfRouting + */ + public function getRoute($name) + { + return null; + } + + /** + * @see sfRouting + */ + public function setRoutes($routes) + { + return array(); + } + + /** + * @see sfRouting + */ + public function hasRoutes() + { + return false; + } + + /** + * @see sfRouting + */ + public function clearRoutes() {} + + protected function mergeArrays($arr1, $arr2) + { + foreach ($arr2 as $key => $value) { + $arr1[$key] = $value; + } + + return $arr1; + } +} diff --git a/tests/sfParameterHolderProxyTestCase.php b/tests/sfParameterHolderProxyTestCase.php new file mode 100644 index 000000000..a809cc63f --- /dev/null +++ b/tests/sfParameterHolderProxyTestCase.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use PHPUnit\Framework\TestCase; + +/** + * @internal + * + * @coversNothing + */ +class sfParameterHolderProxyTestCase extends TestCase +{ + protected string $methodName = 'parameter'; + protected object $object; + + public function testMethodHolderProxy() + { + $hasMethod = 'has'.ucfirst($this->methodName); + $getMethod = 'get'.ucfirst($this->methodName); + $setMethod = 'set'.ucfirst($this->methodName); + $holderMethod = 'get'.ucfirst($this->methodName).'Holder'; + + $namespaced = $this->object->{$holderMethod}() instanceof sfNamespacedParameterHolder ? true : false; + + $this->assertInstanceOf($namespaced ? 'sfNamespacedParameterHolder' : 'sfParameterHolder', $this->object->{$holderMethod}(), "->{$holderMethod}() returns a parameter holder instance"); + $this->assertSame(false, $this->object->{$hasMethod}('foo'), "->{$hasMethod}() returns false if the {$this->methodName} does not exist"); + $this->assertSame('default', $this->object->{$getMethod}('foo', 'default'), "->{$getMethod}() returns the default value if {$this->methodName} does not exist"); + $this->object->{$setMethod}('foo', 'bar'); + $this->assertSame(true, $this->object->{$hasMethod}('foo'), "->{$hasMethod}() returns true if the {$this->methodName} exists"); + $this->assertSame($this->object->{$holderMethod}()->has('foo'), $this->object->{$hasMethod}('foo'), "->{$hasMethod}() is a proxy method"); + $this->assertSame('bar', $this->object->{$getMethod}('foo'), "->{$getMethod}() returns the value of the {$this->methodName}"); + $this->assertSame($this->object->{$holderMethod}()->get('foo'), $this->object->{$getMethod}('foo'), "->{$getMethod}() is a proxy method"); + $this->assertSame('bar', $this->object->{$getMethod}('foo', 'default'), "->{$getMethod}() does not return the default value if the {$this->methodName} exists"); + + if ($namespaced) { + $this->object->{$setMethod}('foo1', 'bar1', 'mynamespace'); + $this->assertSame(false, $this->object->{$hasMethod}('foo1'), "->{$hasMethod}() takes a namespace as its second parameter"); + $this->assertSame(true, $this->object->{$hasMethod}('foo1', 'mynamespace'), "->{$hasMethod}() takes a namespace as its second parameter"); + $this->assertSame('bar1', $this->object->{$getMethod}('foo1', 'default', 'mynamespace'), "->{$getMethod}() takes a namespace as its third parameter"); + } + + $this->object->{$setMethod}('foo2', 'bar2'); + $this->object->{$holderMethod}()->set('foo3', 'bar3'); + $this->assertSame($this->object->{$holderMethod}()->get('foo2'), $this->object->{$getMethod}('foo2'), "->{$setMethod}() is a proxy method"); + $this->assertSame($this->object->{$holderMethod}()->get('foo3'), $this->object->{$getMethod}('foo3'), "->{$setMethod}() is a proxy method"); + } +} From 11a5e44ad310432441acf91ff51ac4a2cf765438 Mon Sep 17 00:00:00 2001 From: Karoly Gossler Date: Fri, 16 Feb 2024 08:32:39 +0100 Subject: [PATCH 3/4] cleanup this for now --- tests/sfParameterHolderProxyTestCase.php | 54 ------------------------ 1 file changed, 54 deletions(-) delete mode 100644 tests/sfParameterHolderProxyTestCase.php diff --git a/tests/sfParameterHolderProxyTestCase.php b/tests/sfParameterHolderProxyTestCase.php deleted file mode 100644 index a809cc63f..000000000 --- a/tests/sfParameterHolderProxyTestCase.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use PHPUnit\Framework\TestCase; - -/** - * @internal - * - * @coversNothing - */ -class sfParameterHolderProxyTestCase extends TestCase -{ - protected string $methodName = 'parameter'; - protected object $object; - - public function testMethodHolderProxy() - { - $hasMethod = 'has'.ucfirst($this->methodName); - $getMethod = 'get'.ucfirst($this->methodName); - $setMethod = 'set'.ucfirst($this->methodName); - $holderMethod = 'get'.ucfirst($this->methodName).'Holder'; - - $namespaced = $this->object->{$holderMethod}() instanceof sfNamespacedParameterHolder ? true : false; - - $this->assertInstanceOf($namespaced ? 'sfNamespacedParameterHolder' : 'sfParameterHolder', $this->object->{$holderMethod}(), "->{$holderMethod}() returns a parameter holder instance"); - $this->assertSame(false, $this->object->{$hasMethod}('foo'), "->{$hasMethod}() returns false if the {$this->methodName} does not exist"); - $this->assertSame('default', $this->object->{$getMethod}('foo', 'default'), "->{$getMethod}() returns the default value if {$this->methodName} does not exist"); - $this->object->{$setMethod}('foo', 'bar'); - $this->assertSame(true, $this->object->{$hasMethod}('foo'), "->{$hasMethod}() returns true if the {$this->methodName} exists"); - $this->assertSame($this->object->{$holderMethod}()->has('foo'), $this->object->{$hasMethod}('foo'), "->{$hasMethod}() is a proxy method"); - $this->assertSame('bar', $this->object->{$getMethod}('foo'), "->{$getMethod}() returns the value of the {$this->methodName}"); - $this->assertSame($this->object->{$holderMethod}()->get('foo'), $this->object->{$getMethod}('foo'), "->{$getMethod}() is a proxy method"); - $this->assertSame('bar', $this->object->{$getMethod}('foo', 'default'), "->{$getMethod}() does not return the default value if the {$this->methodName} exists"); - - if ($namespaced) { - $this->object->{$setMethod}('foo1', 'bar1', 'mynamespace'); - $this->assertSame(false, $this->object->{$hasMethod}('foo1'), "->{$hasMethod}() takes a namespace as its second parameter"); - $this->assertSame(true, $this->object->{$hasMethod}('foo1', 'mynamespace'), "->{$hasMethod}() takes a namespace as its second parameter"); - $this->assertSame('bar1', $this->object->{$getMethod}('foo1', 'default', 'mynamespace'), "->{$getMethod}() takes a namespace as its third parameter"); - } - - $this->object->{$setMethod}('foo2', 'bar2'); - $this->object->{$holderMethod}()->set('foo3', 'bar3'); - $this->assertSame($this->object->{$holderMethod}()->get('foo2'), $this->object->{$getMethod}('foo2'), "->{$setMethod}() is a proxy method"); - $this->assertSame($this->object->{$holderMethod}()->get('foo3'), $this->object->{$getMethod}('foo3'), "->{$setMethod}() is a proxy method"); - } -} From 3d21f5a1aaa70a6bcaa3722140d73670d9296ef8 Mon Sep 17 00:00:00 2001 From: Karoly Gossler Date: Fri, 16 Feb 2024 09:15:59 +0100 Subject: [PATCH 4/4] removed coversNothing --- tests/action/sfComponentTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/action/sfComponentTest.php b/tests/action/sfComponentTest.php index 91e695b50..2f151c54c 100644 --- a/tests/action/sfComponentTest.php +++ b/tests/action/sfComponentTest.php @@ -15,8 +15,6 @@ /** * @internal - * - * @coversNothing */ class sfComponentTest extends sfEventDispatcherTestCase {