diff --git a/.gitignore b/.gitignore index eb2af7b..fbb1132 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ composer.phar build/ test/temp/ vendor/ +*.cache diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 14bb468..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,82 +0,0 @@ -before_script: -# Install dependencies -- set -xe -- apt-get update -yqq -- apt-get install git zip unzip -yqq - -stages: - - build - - test - - deploy - -build:composer: - image: php:7.2 - stage: build - script: - - curl -sS https://getcomposer.org/installer | php - - php composer.phar install - cache: - key: "$CI_BUILD_REF_$CI_BUILD_REF_NAME" - paths: - - vendor/ - -test:7.1: - stage: test - image: php:7.1 - script: - - vendor/bin/phpunit -c test/phpunit.xml - cache: - key: "$CI_BUILD_REF_$CI_BUILD_REF_NAME" - paths: - - vendor - -test:7.2: - stage: test - image: php:7.2 - script: - - vendor/bin/phpunit -c test/phpunit.xml - cache: - key: "$CI_BUILD_REF_$CI_BUILD_REF_NAME" - paths: - - vendor/ - -test:7.3: - stage: test - image: php:7.3 - script: - - vendor/bin/phpunit -c test/phpunit.xml - cache: - key: "$CI_BUILD_REF_$CI_BUILD_REF_NAME" - paths: - - vendor/ - -test:coverage: - stage: test - image: php:7.2 - script: - - pecl install xdebug - - docker-php-ext-enable xdebug - - vendor/bin/phpunit -c test/phpunit.xml --coverage-text - cache: - key: "$CI_BUILD_REF_$CI_BUILD_REF_NAME" - paths: - - vendor/ - -release: - stage: deploy - image: php:7.2 - only: - - master - script: - - pecl install xdebug - - docker-php-ext-enable xdebug - - vendor/bin/phpunit -c test/phpunit.xml --coverage-text - artifacts: - name: "${CI_BUILD_NAME}_${CI_BUILD_REF_NAME}" - paths: - - build/ - expire_in: 3 weeks - cache: - key: "$CI_BUILD_REF_$CI_BUILD_REF_NAME" - paths: - - vendor/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 4930ba4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: php - -php: - - 7.1 - - 7.2 - - 7.3 - -script: - - php vendor/bin/phpunit -v -c test/phpunit.xml --coverage-text - -before_script: - - composer install diff --git a/composer.json b/composer.json index cb9b22f..0493d2d 100644 --- a/composer.json +++ b/composer.json @@ -13,12 +13,12 @@ } ], "require": { - "php": ">=7.3.0", + "php": ">=7.4.0", "fuzeworks/core": "~1.2.0" }, "require-dev": { - "phpunit/phpunit": "^7", - "mikey179/vfsstream": "1.6.5" + "phpunit/phpunit": "^9", + "mikey179/vfsstream": "~1.6.0" }, "autoload": { "psr-4": { diff --git a/src/Config/config.routing.php b/src/Config/config.routing.php index a339f4f..5efa060 100644 --- a/src/Config/config.routing.php +++ b/src/Config/config.routing.php @@ -39,5 +39,6 @@ return array( 'default_view' => 'index', 'default_viewType' => 'standard', 'default_viewMethod' => 'index', + 'default_namespacePrefix' => '\Application\\' ); diff --git a/src/FuzeWorks/Event/RouterLoadCallableEvent.php b/src/FuzeWorks/Event/RouterLoadCallableEvent.php index f403b72..96c564f 100644 --- a/src/FuzeWorks/Event/RouterLoadCallableEvent.php +++ b/src/FuzeWorks/Event/RouterLoadCallableEvent.php @@ -65,6 +65,13 @@ class RouterLoadCallableEvent extends Event */ public $matches; + /** + * The static route configuration + * + * @var array + */ + public $routeData; + /** * The route which resulted in this callable being loaded * @@ -72,10 +79,11 @@ class RouterLoadCallableEvent extends Event */ public $route; - public function init(callable $callable, array $matches, string $route) + public function init(callable $callable, array $matches, array $routeData, string $route) { $this->callable = $callable; $this->matches = $matches; + $this->routeData = $routeData; $this->route = $route; } diff --git a/src/FuzeWorks/Event/RouterLoadViewAndControllerEvent.php b/src/FuzeWorks/Event/RouterLoadViewAndControllerEvent.php index dcb9c82..7ec8e6d 100644 --- a/src/FuzeWorks/Event/RouterLoadViewAndControllerEvent.php +++ b/src/FuzeWorks/Event/RouterLoadViewAndControllerEvent.php @@ -79,6 +79,13 @@ class RouterLoadViewAndControllerEvent extends Event */ public $viewParameters; + /** + * The namespace to use to load the View and Controller + * + * @var string + */ + public $namespacePrefix; + /** * The route that resulted in this controller and view * @@ -93,12 +100,13 @@ class RouterLoadViewAndControllerEvent extends Event */ public $controller; - public function init(string $viewName, string $viewType, array $viewMethods, string $viewParameters, string $route) + public function init(string $viewName, string $viewType, array $viewMethods, string $viewParameters, string $namespacePrefix, string $route) { $this->viewName = $viewName; $this->viewType = $viewType; $this->viewMethods = $viewMethods; $this->viewParameters = $viewParameters; + $this->namespacePrefix = $namespacePrefix; $this->route = $route; } diff --git a/src/FuzeWorks/Router.php b/src/FuzeWorks/Router.php index fab4604..6e17937 100644 --- a/src/FuzeWorks/Router.php +++ b/src/FuzeWorks/Router.php @@ -70,6 +70,11 @@ class Router */ protected $matches = null; + /** + * @var array|null + */ + protected $routeData = null; + /** * The current route used * @@ -198,19 +203,23 @@ class Router /** * @param string $path + * @param array $routes Optional routes for not using the default * @return mixed * @throws NotFoundException * @throws RouterException * @throws HaltException */ - public function route(string $path) + public function route(string $path, array $routes = []) { + // Select the routes to use + $routes = empty($routes) ? $this->routes : $routes; + // Check all the provided custom paths, ordered by priority for ($i=Priority::getHighestPriority(); $i<=Priority::getLowestPriority(); $i++) { - if (!isset($this->routes[$i])) + if (!isset($routes[$i])) continue; - foreach ($this->routes[$i] as $route => $routeConfig) + foreach ($routes[$i] as $route => $routeConfig) { // Match the path against the routes if (!preg_match('#^'.$route.'$#', $path, $matches)) @@ -219,29 +228,30 @@ class Router // Save the matches Logger::log("Route matched: '" . $route . "' with " . Priority::getPriority($i)); $this->matches = $matches; + $this->routeData = $routeConfig; $this->route = $route; $this->callable = null; // Call callable if routeConfig is callable, so routeConfig can be replaced // This is an example of 'Dynamic Rewrite' // e.g: '.*$' => callable - if (is_callable($routeConfig)) - $routeConfig = call_user_func_array($routeConfig, [$matches]); + if (is_callable($this->routeData)) + $this->routeData = call_user_func_array($this->routeData, [$matches]); // If routeConfig is an array, multiple things might be at hand - if (is_array($routeConfig)) + if (is_array($this->routeData)) { // Replace defaultCallable if a custom callable is provided // This is an example of 'Custom Callable' // e.g: '.*$' => ['callable' => [$object, 'method']] - if (isset($routeConfig['callable']) && is_callable($routeConfig['callable'])) - $this->callable = $routeConfig['callable']; + if (isset($this->routeData['callable']) && is_callable($this->routeData['callable'])) + $this->callable = $this->routeData['callable']; // If the route provides a configuration, use that // This is an example of 'Static Rewrite' // e.g: '.*$' => ['viewName' => 'custom', 'viewType' => 'cli', 'function' => 'index'] else - $this->matches = array_merge($this->matches, $routeConfig); + $this->matches = array_merge($this->matches, $this->routeData); } // If no custom callable is provided, use default @@ -250,7 +260,7 @@ class Router $this->callable = [$this, 'defaultCallable']; // Attempt and load callable. If false, continue - $output = $this->loadCallable($this->callable, $this->matches, $route); + $output = $this->loadCallable($this->callable, $this->matches, $this->routeData, $route); if (is_bool($output) && $output === FALSE) { Logger::log('Callable not satisfied, skipping to next callable'); @@ -267,12 +277,13 @@ class Router /** * @param callable $callable * @param array $matches + * @param array $routeData * @param string $route * @return mixed - * @throws RouterException * @throws HaltException + * @throws RouterException */ - protected function loadCallable(callable $callable, array $matches, string $route) + protected function loadCallable(callable $callable, array $matches, array $routeData, string $route) { // Log the input to the logger Logger::newLevel('Loading callable with matches:'); @@ -286,6 +297,7 @@ class Router $event = Events::fireEvent('routerLoadCallableEvent', $callable, $matches, + $routeData, $route ); } catch (EventException $e) { @@ -297,29 +309,34 @@ class Router throw new HaltException("Will not load callable. Cancelled by routerLoadCallableEvent."); // Invoke callable - $output = call_user_func_array($event->callable, [$event->matches, $event->route]); + $output = call_user_func_array($event->callable, [$event->matches, $event->routeData, $event->route]); Logger::stopLevel(); return $output; } /** * @param array $matches + * @param array $routeData * @param string $route * @return mixed * @throws HaltException * @throws RouterException * @todo Use $route and send it to the view */ - public function defaultCallable(array $matches, string $route) + public function defaultCallable(array $matches, array $routeData, string $route) { Logger::log('defaultCallable called'); // Prepare variables + // Variables from matches $viewName = !empty($matches['viewName']) ? $matches['viewName'] : $this->config->routing->default_view; - $viewType = !empty($matches['viewType']) ? $matches['viewType'] : $this->config->routing->default_viewType; $viewMethod = !empty($matches['viewMethod']) ? $matches['viewMethod'] : $this->config->routing->default_viewMethod; $viewParameters = !empty($matches['viewParameters']) ? $matches['viewParameters'] : ''; + // Variables from routeData + $viewType = !empty($routeData['viewType']) ? $routeData['viewType'] : $this->config->routing->default_viewType; + $namespacePrefix = !empty($routeData['namespacePrefix']) ? $routeData['namespacePrefix'] : $this->config->routing->default_namespacePrefix; + try { /** @var RouterLoadViewAndControllerEvent $event */ $event = Events::fireEvent('routerLoadViewAndControllerEvent', @@ -328,6 +345,7 @@ class Router // ViewMethod is provided as a Priority::NORMAL method [3 => [$viewMethod]], $viewParameters, + $namespacePrefix, $route ); } catch (EventException $e) { @@ -340,7 +358,7 @@ class Router // First receive the controller try { - $this->controller = (!is_null($event->controller) ? $event->controller : $this->controllers->get($event->viewName)); + $this->controller = (!is_null($event->controller) ? $event->controller : $this->controllers->get($event->viewName, [], $event->namespacePrefix . 'Controller\\')); } catch (ControllerException $e) { throw new RouterException("Could not load view. Controllers::get threw ControllerException: '".$e->getMessage()."'"); } catch (NotFoundException $e) { @@ -350,7 +368,7 @@ class Router // Then try and receive the view try { - $this->view = $this->views->get($event->viewName, $this->controller, $event->viewType); + $this->view = $this->views->get($event->viewName, $this->controller, $event->viewType, [], $event->namespacePrefix. 'View\\'); } catch (ViewException $e) { throw new RouterException("Could not load view. Views::get threw ViewException: '".$e->getMessage()."'"); } catch (NotFoundException $e) { diff --git a/test/autoload.php b/test/autoload.php index 03fa03c..548fa67 100644 --- a/test/autoload.php +++ b/test/autoload.php @@ -38,10 +38,7 @@ chdir(dirname(__DIR__)); // Load the FuzeWorks container -$container = require('test/bootstrap.php'); - -// Load the test abstract -require_once 'mcr/MVCRTestAbstract.php'; +$container = require('bootstrap.php'); // Reset error and exception handlers restore_error_handler(); diff --git a/test/bootstrap.php b/test/bootstrap.php index 7952515..7fbe9d7 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -44,7 +44,6 @@ $configurator->setLogDirectory(dirname(__FILE__) . '/temp'); // Other values $configurator->setTimeZone('Europe/Amsterdam'); -$configurator->enableDebugMode(false); $configurator->setDebugAddress('NONE'); // Implement the MVCR Component diff --git a/test/controllers/controller.testdefaultcallablecustomnamespace.php b/test/controllers/controller.testdefaultcallablecustomnamespace.php new file mode 100644 index 0000000..6293b5f --- /dev/null +++ b/test/controllers/controller.testdefaultcallablecustomnamespace.php @@ -0,0 +1,44 @@ +controllers = new Controllers(); - $this->controllers->addComponentPath('test'.DS.'controllers'); + $this->controllers->addComponentPath('controllers'); + } + + /** + * Remove all listeners before the next test starts. + */ + public function tearDown(): void + { + // Clear all events created by tests + Events::$listeners = array(); + + // Reset all config files + Factory::getInstance()->config->discardConfigFiles(); } /** @@ -77,7 +92,6 @@ class ControllersTest extends MVCRTestAbstract * @depends testGetControllerFromClass * @covers ::get * @covers ::loadController - * @expectedException \FuzeWorks\Exception\ControllerException */ public function testGetControllerFromClassInvalidInstance() { @@ -87,6 +101,7 @@ class ControllersTest extends MVCRTestAbstract class_alias($mockFakeControllerClass, $mockFakeControllerClass . 'Controller'); // Try and fetch + $this->expectException(ControllerException::class); $this->controllers->get($mockFakeControllerClass, [], '\\'); } @@ -120,10 +135,10 @@ class ControllersTest extends MVCRTestAbstract /** * @covers ::get - * @expectedException \FuzeWorks\Exception\ControllerException */ public function testGetControllerInvalidName() { + $this->expectException(ControllerException::class); $this->controllers->get('', [], '\\'); } @@ -141,10 +156,10 @@ class ControllersTest extends MVCRTestAbstract * @depends testGetControllerFromFile * @covers ::get * @covers ::loadController - * @expectedException \FuzeWorks\Exception\ControllerException */ public function testGetControllerFromFileInvalidInstance() { + $this->expectException(ControllerException::class); $this->controllers->get('ControllerInvalidInstance'); } @@ -156,8 +171,8 @@ class ControllersTest extends MVCRTestAbstract public function testDifferentComponentPathPriority() { // Add the directories for this test - $this->controllers->addComponentPath('test'.DS.'controllers'.DS.'TestDifferentComponentPathPriority'.DS.'Lowest', Priority::LOWEST); - $this->controllers->addComponentPath('test'.DS.'controllers'.DS.'TestDifferentComponentPathPriority'.DS.'Highest', Priority::HIGHEST); + $this->controllers->addComponentPath('controllers'.DS.'TestDifferentComponentPathPriority'.DS.'Lowest', Priority::LOWEST); + $this->controllers->addComponentPath('controllers'.DS.'TestDifferentComponentPathPriority'.DS.'Highest', Priority::HIGHEST); // Load the controller and assert it is the correct type $controller = $this->controllers->get('TestDifferentComponentPathPriority'); @@ -182,10 +197,10 @@ class ControllersTest extends MVCRTestAbstract * @depends testGetControllerFromFile * @covers ::get * @covers ::loadController - * @expectedException \FuzeWorks\Exception\NotFoundException */ public function testControllerNotFound() { + $this->expectException(NotFoundException::class); $this->controllers->get('NotFound'); } @@ -193,7 +208,6 @@ class ControllersTest extends MVCRTestAbstract * @depends testGetControllerFromClass * @covers ::get * @covers \FuzeWorks\Event\ControllerGetEvent::init - * @expectedException \FuzeWorks\Exception\ControllerException */ public function testControllerGetEvent() { @@ -208,13 +222,13 @@ class ControllersTest extends MVCRTestAbstract $event->setCancelled(true); }, 'controllerGetEvent', Priority::NORMAL); + $this->expectException(ControllerException::class); $this->controllers->get('SomeControllerName', ['some_path'], 'SomeNamespace', 'Some Argument'); } /** * @depends testControllerGetEvent * @covers ::get - * @expectedException \FuzeWorks\Exception\ControllerException */ public function testCancelGetController() { @@ -223,6 +237,7 @@ class ControllersTest extends MVCRTestAbstract $event->setCancelled(true); }, 'controllerGetEvent', Priority::NORMAL); + $this->expectException(ControllerException::class); $this->controllers->get('SomeController', [], '\\'); } diff --git a/test/mcr/ModelsTest.php b/test/mcr/ModelsTest.php index 50a8683..3e9c95e 100644 --- a/test/mcr/ModelsTest.php +++ b/test/mcr/ModelsTest.php @@ -36,15 +36,19 @@ use FuzeWorks\Event\ModelGetEvent; use FuzeWorks\Events; +use FuzeWorks\Exception\ModelException; +use FuzeWorks\Exception\NotFoundException; +use FuzeWorks\Factory; use FuzeWorks\Model; use FuzeWorks\Models; use FuzeWorks\Priority; +use PHPUnit\Framework\TestCase; /** * Class ModelsTest * @coversDefaultClass \FuzeWorks\Models */ -class ModelsTest extends MVCRTestAbstract +class ModelsTest extends TestCase { /** @@ -52,10 +56,22 @@ class ModelsTest extends MVCRTestAbstract */ protected $models; - public function setUp() + public function setUp(): void { $this->models = new Models(); - $this->models->addComponentPath('test'.DS.'models'); + $this->models->addComponentPath('models'); + } + + /** + * Remove all listeners before the next test starts. + */ + public function tearDown(): void + { + // Clear all events created by tests + Events::$listeners = array(); + + // Reset all config files + Factory::getInstance()->config->discardConfigFiles(); } /** @@ -77,7 +93,6 @@ class ModelsTest extends MVCRTestAbstract * @depends testGetModelFromClass * @covers ::get * @covers ::loadModel - * @expectedException \FuzeWorks\Exception\ModelException */ public function testGetModelFromClassInvalidInstance() { @@ -87,6 +102,7 @@ class ModelsTest extends MVCRTestAbstract class_alias($mockFakeModelClass, $mockFakeModelClass . 'Model'); // Try and fetch + $this->expectException(ModelException::class); $this->models->get($mockFakeModelClass, [], '\\'); } @@ -120,10 +136,10 @@ class ModelsTest extends MVCRTestAbstract /** * @covers ::get - * @expectedException \FuzeWorks\Exception\ModelException */ public function testGetModelInvalidName() { + $this->expectException(ModelException::class); $this->models->get('', [], '\\'); } @@ -141,10 +157,10 @@ class ModelsTest extends MVCRTestAbstract * @depends testGetModelFromFile * @covers ::get * @covers ::loadModel - * @expectedException \FuzeWorks\Exception\ModelException */ public function testGetModelFromFileInvalidInstance() { + $this->expectException(ModelException::class); $this->models->get('ModelInvalidInstance'); } @@ -156,8 +172,8 @@ class ModelsTest extends MVCRTestAbstract public function testDifferentComponentPathPriority() { // Add the directories for this test - $this->models->addComponentPath('test'.DS.'models'.DS.'TestDifferentComponentPathPriority'.DS.'Lowest', Priority::LOWEST); - $this->models->addComponentPath('test'.DS.'models'.DS.'TestDifferentComponentPathPriority'.DS.'Highest', Priority::HIGHEST); + $this->models->addComponentPath('models'.DS.'TestDifferentComponentPathPriority'.DS.'Lowest', Priority::LOWEST); + $this->models->addComponentPath('models'.DS.'TestDifferentComponentPathPriority'.DS.'Highest', Priority::HIGHEST); // Load the model and assert it is the correct type $model = $this->models->get('TestDifferentComponentPathPriority'); @@ -182,10 +198,10 @@ class ModelsTest extends MVCRTestAbstract * @depends testGetModelFromFile * @covers ::get * @covers ::loadModel - * @expectedException \FuzeWorks\Exception\NotFoundException */ public function testModelNotFound() { + $this->expectException(NotFoundException::class); $this->models->get('NotFound'); } @@ -193,7 +209,6 @@ class ModelsTest extends MVCRTestAbstract * @depends testGetModelFromClass * @covers ::get * @covers \FuzeWorks\Event\ModelGetEvent::init - * @expectedException \FuzeWorks\Exception\ModelException */ public function testModelGetEvent() { @@ -208,13 +223,13 @@ class ModelsTest extends MVCRTestAbstract $event->setCancelled(true); }, 'modelGetEvent', Priority::NORMAL); + $this->expectException(ModelException::class); $this->models->get('SomeModelName', ['some_path'], 'SomeNamespace', 'Some Argument'); } /** * @depends testModelGetEvent * @covers ::get - * @expectedException \FuzeWorks\Exception\ModelException */ public function testCancelGetModel() { @@ -223,6 +238,7 @@ class ModelsTest extends MVCRTestAbstract $event->setCancelled(true); }, 'modelGetEvent', Priority::NORMAL); + $this->expectException(ModelException::class); $this->models->get('SomeModel', [], '\\'); } diff --git a/test/mcr/RouterTest.php b/test/mcr/RouterTest.php index de9fe7a..32d0a1f 100644 --- a/test/mcr/RouterTest.php +++ b/test/mcr/RouterTest.php @@ -36,15 +36,18 @@ use FuzeWorks\Config; use FuzeWorks\Events; +use FuzeWorks\Exception\HaltException; +use FuzeWorks\Exception\NotFoundException; use FuzeWorks\Factory; use FuzeWorks\Priority; use FuzeWorks\Router; +use PHPUnit\Framework\TestCase; /** * Class RouterTest * @coversDefaultClass \FuzeWorks\Router */ -class RouterTest extends MVCRTestAbstract +class RouterTest extends TestCase { /** @@ -61,15 +64,27 @@ class RouterTest extends MVCRTestAbstract */ protected $config; - public function setUp() + public function setUp(): void { // Get required classes $this->router = new Router(); $this->config = Factory::getInstance()->config; // Append required routes - Factory::getInstance()->controllers->addComponentPath('test' . DS . 'controllers'); - Factory::getInstance()->views->addComponentPath('test' . DS . 'views'); + Factory::getInstance()->controllers->addComponentPath('controllers'); + Factory::getInstance()->views->addComponentPath('views'); + } + + /** + * Remove all listeners before the next test starts. + */ + public function tearDown(): void + { + // Clear all events created by tests + Events::$listeners = array(); + + // Reset all config files + Factory::getInstance()->config->discardConfigFiles(); } /** @@ -203,13 +218,16 @@ class RouterTest extends MVCRTestAbstract { $matches = [ 'viewName' => 'TestDefaultCallable', - 'viewType' => 'test', 'viewMethod' => 'someMethod' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); - $this->assertEquals('Verify Output', $this->router->defaultCallable($matches, '.*$')); + $this->assertEquals('Verify Output', $this->router->defaultCallable($matches, $data, '.*$')); $this->assertInstanceOf('\Application\Controller\TestDefaultCallableController', $this->router->getCurrentController()); $this->assertInstanceOf('\Application\View\TestDefaultCallableTestView', $this->router->getCurrentView()); } @@ -222,13 +240,16 @@ class RouterTest extends MVCRTestAbstract { $matches = [ 'viewName' => 'TestDefaultCallable', - 'viewType' => 'test', 'viewMethod' => 'missing' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); - $this->assertFalse($this->router->defaultCallable($matches, '.*$')); + $this->assertFalse($this->router->defaultCallable($matches, $data, '.*$')); $this->assertInstanceOf('\Application\Controller\TestDefaultCallableController', $this->router->getCurrentController()); $this->assertInstanceOf('\Application\View\TestDefaultCallableTestView', $this->router->getCurrentView()); } @@ -241,13 +262,16 @@ class RouterTest extends MVCRTestAbstract { $matches = [ 'viewName' => 'TestDefaultCallableMissingView', - 'viewType' => 'test', 'viewMethod' => 'missing' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); - $this->assertFalse($this->router->defaultCallable($matches, '.*$')); + $this->assertFalse($this->router->defaultCallable($matches, $data,'.*$')); $this->assertInstanceOf('\Application\Controller\TestDefaultCallableMissingViewController', $this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); } @@ -260,13 +284,16 @@ class RouterTest extends MVCRTestAbstract { $matches = [ 'viewName' => 'TestDefaultCallableMissingController', - 'viewType' => 'test', 'viewMethod' => 'missing' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); - $this->assertFalse($this->router->defaultCallable($matches, '.*$')); + $this->assertFalse($this->router->defaultCallable($matches, $data, '.*$')); $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); } @@ -274,19 +301,23 @@ class RouterTest extends MVCRTestAbstract /** * @depends testDefaultCallable * @covers ::defaultCallable - * @expectedException \FuzeWorks\Exception\HaltException */ public function testDefaultCallableHaltByView() { $matches = [ 'viewName' => 'TestDefaultCallableHalt', - 'viewType' => 'test', 'viewMethod' => 'someMethod' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); - $this->router->defaultCallable($matches, '.*$'); + + $this->expectException(HaltException::class); + $this->router->defaultCallable($matches, $data,'.*$'); $this->assertInstanceOf('\Application\Controller\TestDefaultCallableHaltController', $this->router->getCurrentController()); $this->assertInstanceOf('\Application\View\TestDefaultCallableHaltTestView', $this->router->getCurrentView()); } @@ -298,31 +329,59 @@ class RouterTest extends MVCRTestAbstract public function testDefaultCallableEmptyName() { $matches = [ - 'viewType' => 'test', 'viewMethod' => 'someMethod' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); - $this->assertFalse($this->router->defaultCallable($matches, '.*$')); + $this->assertFalse($this->router->defaultCallable($matches, $data, '.*$')); $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); } + /** + * @depends testDefaultCallable + * @covers ::defaultCallable + */ + public function testDefaultCallableCustomNamespace() + { + $matches = [ + 'viewName' => 'TestDefaultCallableCustomNamespace', + 'viewMethod' => 'someMethod' + ]; + + $data = [ + 'viewType' => 'test', + 'namespacePrefix' => '\Custom\\' + ]; + + $this->assertNull($this->router->getCurrentController()); + $this->assertNull($this->router->getCurrentView()); + $this->assertEquals('Verify Output, with custom namespace!', $this->router->defaultCallable($matches, $data, '.*$')); + $this->assertInstanceOf('\Custom\Controller\TestDefaultCallableCustomNamespaceController', $this->router->getCurrentController()); + $this->assertInstanceOf('\Custom\View\TestDefaultCallableCustomNamespaceTestView', $this->router->getCurrentView()); + } + /** * @depends testDefaultCallable * @covers ::defaultCallable * @covers \FuzeWorks\Event\RouterLoadViewAndControllerEvent::init - * @expectedException \FuzeWorks\Exception\HaltException */ public function testDefaultCallableHaltByEvent() { $matches = [ 'viewName' => 'TestDefaultCallable', - 'viewType' => 'test', 'viewMethod' => 'missing' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); @@ -335,7 +394,8 @@ class RouterTest extends MVCRTestAbstract $event->setCancelled(true); }, 'routerLoadViewAndControllerEvent'); - $this->router->defaultCallable($matches, '.*$'); + $this->expectException(HaltException::class); + $this->router->defaultCallable($matches, $data, '.*$'); } /** @@ -347,10 +407,13 @@ class RouterTest extends MVCRTestAbstract { $matches = [ 'viewName' => 'TestDefaultCallable', - 'viewType' => 'test', 'viewMethod' => 'missing' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); @@ -361,7 +424,7 @@ class RouterTest extends MVCRTestAbstract $event->overrideController($mockController); }, 'routerLoadViewAndControllerEvent', Priority::NORMAL, $mockController); - $this->router->defaultCallable($matches, '.*$'); + $this->router->defaultCallable($matches, $data, '.*$'); $this->assertEquals($mockController, $this->router->getCurrentController()); } @@ -374,10 +437,13 @@ class RouterTest extends MVCRTestAbstract { $matches = [ 'viewName' => 'TestDefaultCallableChangeMethod', - 'viewType' => 'test', 'viewMethod' => 'index' ]; + $data = [ + 'viewType' => 'test' + ]; + $this->assertNull($this->router->getCurrentController()); $this->assertNull($this->router->getCurrentView()); @@ -388,7 +454,7 @@ class RouterTest extends MVCRTestAbstract $event->addMethod('altered', Priority::HIGH); }, 'routerLoadViewAndControllerEvent', Priority::NORMAL, $mockController); - $this->assertEquals('Altered!', $this->router->defaultCallable($matches, '.*$')); + $this->assertEquals('Altered!', $this->router->defaultCallable($matches, $data, '.*$')); } /* route() ------------------------------------------------------------ */ @@ -401,7 +467,7 @@ class RouterTest extends MVCRTestAbstract public function testRoute() { // Add route first - $this->router->addRoute('(?P.*?)(|\/(?P.*?)(|\/(?P.*?)))(|\.(?P.*?))'); + $this->router->addRoute('(?P.*?)(|\/(?P.*?)(|\/(?P.*?))).test', ['viewType' => 'test']); // Create mock view and controller $mockController = $this->getMockBuilder('\FuzeWorks\Controller')->getMock(); @@ -418,20 +484,41 @@ class RouterTest extends MVCRTestAbstract /** * @depends testRoute * @covers ::route - * @expectedException \FuzeWorks\Exception\NotFoundException + */ + public function testDistinctRoute() + { + // Create mock view and controller + $mockController = $this->getMockBuilder('\FuzeWorks\Controller')->getMock(); + $mockView = $this->getMockBuilder('\FuzeWorks\View')->setMethods(['testMethod'])->getMock(); + class_alias(get_class($mockController), '\Application\Controller\TestDistinctRouteController'); + class_alias(get_class($mockView), '\Application\View\TestDistinctRouteTestView'); + + $this->assertNull($this->router->route('testDistinctRoute/testMethod/testParameters.test', [ + 3 => [ + '(?P.*?)(|\/(?P.*?)(|\/(?P.*?))).test' => ['viewType' => 'test'] + ] + ])); + $this->assertInstanceOf('\Application\Controller\TestDistinctRouteController', $this->router->getCurrentController()); + $this->assertInstanceOf('\Application\View\TestDistinctRouteTestView', $this->router->getCurrentView()); + } + + /** + * @depends testRoute + * @covers ::route */ public function testRouteNotFound() { + $this->expectException(NotFoundException::class); $this->router->route('NotFound'); } /** * @depends testRouteNotFound * @covers ::route - * @expectedException \FuzeWorks\Exception\NotFoundException */ public function testRouteNotMatched() { + $this->expectException(NotFoundException::class); $this->router->addRoute('NotMatched'); $this->router->route('NotFound'); } @@ -505,7 +592,7 @@ class RouterTest extends MVCRTestAbstract public function testRouteCustomCallable() { // Create custom callable - $callable = function(array $matches, string $route){ + $callable = function(array $matches, array $data, string $route){ $this->assertEquals('customCallable', $route); $this->assertEquals([0=>'customCallable'], $matches); }; @@ -525,12 +612,11 @@ class RouterTest extends MVCRTestAbstract * @depends testRouteStaticRewrite * @covers ::route * @covers ::loadCallable - * @expectedException \FuzeWorks\Exception\NotFoundException */ public function testRouteUnsatisfiedCallable() { // Create custom callable - $callable = function(array $matches, string $route){ + $callable = function(array $matches, array $data, string $route){ $this->assertEquals('unsatisfiedCallable', $route); $this->assertEquals([0=>'unsatisfiedCallable'], $matches); return false; @@ -544,6 +630,7 @@ class RouterTest extends MVCRTestAbstract ] ); + $this->expectException(NotFoundException::class); $this->assertNull($this->router->route('unsatisfiedCallable')); } diff --git a/test/mcr/ViewsTest.php b/test/mcr/ViewsTest.php index 2b7e3f6..dc9ce2c 100644 --- a/test/mcr/ViewsTest.php +++ b/test/mcr/ViewsTest.php @@ -37,15 +37,19 @@ use FuzeWorks\Controller; use FuzeWorks\Event\ViewGetEvent; use FuzeWorks\Events; +use FuzeWorks\Exception\NotFoundException; +use FuzeWorks\Exception\ViewException; +use FuzeWorks\Factory; use FuzeWorks\Priority; use FuzeWorks\View; use FuzeWorks\Views; +use PHPUnit\Framework\TestCase; /** * Class ViewsTest * @coversDefaultClass \FuzeWorks\Views */ -class ViewsTest extends MVCRTestAbstract +class ViewsTest extends TestCase { /** @@ -58,10 +62,10 @@ class ViewsTest extends MVCRTestAbstract */ protected $mockController; - public function setUp() + public function setUp(): void { $this->views = new Views(); - $this->views->addComponentPath('test'.DS.'views'); + $this->views->addComponentPath('views'); $this->mockController = $this->getMockBuilder(Controller::class)->getMock(); } @@ -80,11 +84,22 @@ class ViewsTest extends MVCRTestAbstract $this->assertInstanceOf($mockViewClass, $this->views->get($mockViewClass, $this->mockController, 'Standard', [], '\\')); } + /** + * Remove all listeners before the next test starts. + */ + public function tearDown(): void + { + // Clear all events created by tests + Events::$listeners = array(); + + // Reset all config files + Factory::getInstance()->config->discardConfigFiles(); + } + /** * @depends testGetViewFromClass * @covers ::get * @covers ::loadView - * @expectedException \FuzeWorks\Exception\ViewException */ public function testGetViewFromClassInvalidInstance() { @@ -94,6 +109,7 @@ class ViewsTest extends MVCRTestAbstract class_alias($mockFakeViewClass, $mockFakeViewClass . 'StandardView'); // Try and fetch + $this->expectException(ViewException::class); $this->views->get($mockFakeViewClass, $this->mockController, 'Standard', [], '\\'); } @@ -127,10 +143,10 @@ class ViewsTest extends MVCRTestAbstract /** * @covers ::get - * @expectedException \FuzeWorks\Exception\ViewException */ public function testGetViewInvalidName() { + $this->expectException(ViewException::class); $this->views->get('', $this->mockController, 'Standard', [], '\\'); } @@ -148,10 +164,10 @@ class ViewsTest extends MVCRTestAbstract * @depends testGetViewFromFile * @covers ::get * @covers ::loadView - * @expectedException \FuzeWorks\Exception\ViewException */ public function testGetViewFromFileInvalidInstance() { + $this->expectException(ViewException::class); $this->views->get('ViewInvalidInstance', $this->mockController); } @@ -163,8 +179,8 @@ class ViewsTest extends MVCRTestAbstract public function testDifferentComponentPathPriority() { // Add the directories for this test - $this->views->addComponentPath('test'.DS.'views'.DS.'TestDifferentComponentPathPriority'.DS.'Lowest', Priority::LOWEST); - $this->views->addComponentPath('test'.DS.'views'.DS.'TestDifferentComponentPathPriority'.DS.'Highest', Priority::HIGHEST); + $this->views->addComponentPath('views'.DS.'TestDifferentComponentPathPriority'.DS.'Lowest', Priority::LOWEST); + $this->views->addComponentPath('views'.DS.'TestDifferentComponentPathPriority'.DS.'Highest', Priority::HIGHEST); // Load the view and assert it is the correct type $view = $this->views->get('TestDifferentComponentPathPriority', $this->mockController); @@ -189,10 +205,10 @@ class ViewsTest extends MVCRTestAbstract * @depends testGetViewFromFile * @covers ::get * @covers ::loadView - * @expectedException \FuzeWorks\Exception\NotFoundException */ public function testViewNotFound() { + $this->expectException(NotFoundException::class); $this->views->get('NotFound', $this->mockController); } @@ -200,7 +216,6 @@ class ViewsTest extends MVCRTestAbstract * @depends testGetViewFromClass * @covers ::get * @covers \FuzeWorks\Event\ViewGetEvent::init - * @expectedException \FuzeWorks\Exception\ViewException */ public function testViewGetEvent() { @@ -217,13 +232,13 @@ class ViewsTest extends MVCRTestAbstract $event->setCancelled(true); }, 'viewGetEvent', Priority::NORMAL); + $this->expectException(ViewException::class); $this->views->get('SomeViewName', $this->mockController, 'Other', ['some_path'], 'SomeNamespace', 'Some Argument'); } /** * @depends testViewGetEvent * @covers ::get - * @expectedException \FuzeWorks\Exception\ViewException */ public function testCancelGetView() { @@ -232,6 +247,7 @@ class ViewsTest extends MVCRTestAbstract $event->setCancelled(true); }, 'viewGetEvent', Priority::NORMAL); + $this->expectException(ViewException::class); $this->views->get('SomeView', $this->mockController, 'Standard', [], '\\'); } diff --git a/test/phpunit.xml b/test/phpunit.xml index 7708a45..08350ae 100644 --- a/test/phpunit.xml +++ b/test/phpunit.xml @@ -1,34 +1,17 @@ - - + + + + + ../ + + + ../vendor/ + ../test/ + + - + ./ - - - - - - - - - - - ../ - - ../vendor/ - ../test/ - - - \ No newline at end of file diff --git a/test/mcr/MVCRTestAbstract.php b/test/views/view.test.testdefaultcallablecustomnamespace.php similarity index 72% rename from test/mcr/MVCRTestAbstract.php rename to test/views/view.test.testdefaultcallablecustomnamespace.php index 86850c3..9683beb 100644 --- a/test/mcr/MVCRTestAbstract.php +++ b/test/views/view.test.testdefaultcallablecustomnamespace.php @@ -29,32 +29,21 @@ * @license https://opensource.org/licenses/MIT MIT License * * @link http://techfuze.net/fuzeworks - * @since Version 0.0.1 + * @since Version 1.2.0 * * @version Version 1.2.0 */ -use FuzeWorks\Events; -use PHPUnit\Framework\TestCase; -use FuzeWorks\Factory; -use FuzeWorks\Core; +namespace Custom\View; -/** - * Class MVCRTestAbstract. - * - * Resets core components to their original state - */ -abstract class MVCRTestAbstract extends TestCase +use FuzeWorks\View; + +class TestDefaultCallableCustomNamespaceTestView extends View { - /** - * Remove all listeners before the next test starts. - */ - public function tearDown() - { - // Clear all events created by tests - Events::$listeners = array(); - // Reset all config files - Factory::getInstance()->config->discardConfigFiles(); + public function someMethod() + { + return "Verify Output, with custom namespace!"; } -} + +} \ No newline at end of file