/ */ class P4Cms_ModuleTest extends TestCase { /** * Add the path to the test modules and setup module * configuration capabilities. */ public function setUp() { parent::setUp(); P4Cms_Module::reset(); P4Cms_Module::setCoreModulesPath(TEST_ASSETS_PATH . DIRECTORY_SEPARATOR . 'core-modules'); P4Cms_Module::addPackagesPath(TEST_ASSETS_PATH . DIRECTORY_SEPARATOR . 'optional-modules'); // storage adapter is needed for module config. $adapter = new P4Cms_Record_Adapter; $adapter->setConnection($this->p4) ->setBasePath("//depot"); P4Cms_Record::setDefaultAdapter($adapter); } /** * Remove the path to the test modules and clear module * configuration capabilities. */ public function tearDown() { P4Cms_Record::clearDefaultAdapter(); P4Cms_Module::reset(); parent::tearDown(); } /** * Test that known modules can be fetched (and are properly populated), * and that non-existent modules throw a lookup exception. */ public function testFetch() { $module = P4Cms_Module::fetch('Independent'); $this->assertTrue($module instanceof P4Cms_Module); $this->assertTrue($module->getName() == 'Independent'); $this->assertTrue( $module->getPath() == TEST_ASSETS_PATH . DIRECTORY_SEPARATOR . 'optional-modules' . DIRECTORY_SEPARATOR . 'independent' ); $this->assertTrue($module->getDescription() == 'A test module with no dependencies.'); $this->assertTrue(is_array($module->getMaintainerInfo())); $this->assertTrue($module->getMaintainerInfo('name') == 'Perforce Software'); $this->assertTrue($module->getMaintainerInfo('email') == 'support@perforce.com'); $this->assertTrue($module->getMaintainerInfo('url') == 'http://www.perforce.com'); $this->assertTrue($module->getVersion() == '1.0'); $this->assertTrue(count($module->getDependencies()) == 0); // test another known module. $module = P4Cms_Module::fetch('Dependent'); $this->assertTrue($module instanceof P4Cms_Module); // test a core module. $module = P4Cms_Module::fetch('Core'); $this->assertTrue($module instanceof P4Cms_Module); // ensure fetch of non-existent module fails. try { P4Cms_Module::fetch('asdfghjkl'); $this->fail(); } catch (P4Cms_Model_NotFoundException $e) { $this->assertTrue(true); } catch (Exception $e) { $this->fail(); } } /** * Test that fetch all returns entire list of installed modules. */ public function testFetchAll() { // count the core modules. $modules = array(); foreach (new DirectoryIterator(TEST_ASSETS_PATH . DIRECTORY_SEPARATOR . 'core-modules') as $entry) { if ($entry->isDir() && !$entry->isDot()) { $modules[] = $entry->getBasename(); } } // count the optional modules. foreach (new DirectoryIterator(TEST_ASSETS_PATH . DIRECTORY_SEPARATOR . 'optional-modules') as $entry) { if ($entry->isDir() && !$entry->isDot()) { $modules[] = $entry->getBasename(); } } $moduleModels = P4Cms_Module::fetchAll(); $this->assertTrue($moduleModels instanceof P4Cms_Model_Iterator); $this->assertTrue(count($moduleModels) == count(array_unique($modules))); } /** * Test fetching all enabled modules. */ public function testFetchAllEnabled() { // ensure core modules appear. $modules = P4Cms_Module::fetchAllEnabled(); $this->assertTrue(count($modules) == 1); // ensure core modules excluded when true passed. $modules = P4Cms_Module::fetchAllEnabled(true); $this->assertTrue(count($modules) == 0); // ensure that enabled modules appear in list. $module = P4Cms_Module::fetch('Independent'); $module->enable(); P4Cms_Module::clearConfigCache(); $modules = P4Cms_Module::fetchAllEnabled(true); $this->assertTrue(count($modules) == 1); // ensure core modules appear alonside enabled ones. $modules = P4Cms_Module::fetchAllEnabled(); $this->assertTrue(count($modules) == 2); // ensure that enabled modules don't share the same config file // see P4Cms_Module::_getConfigRecords(), static::$_configRecords array // index $module = P4Cms_Module::fetch('Dependent'); $module->enable(); P4Cms_Module::clearConfigCache(); $modules = P4Cms_Module::fetchAllEnabled(); $this->assertTrue(count($modules) == 3); } /** * Test fetchAll for disabled modules. */ public function testFetchAllDisabled() { $modules = P4Cms_Module::fetchAllDisabled(); $this->assertSame( 3, count($modules), 'Expected matching number of results' ); foreach ($modules as $module) { $this->assertFalse( $module->isEnabled(), 'Expected module to be disabled.' ); } // ensure that enabled modules fall out of list. P4Cms_Module::fetch('Independent')->enable(); $modules = P4Cms_Module::fetchAllDisabled(); $this->assertSame( 2, count($modules), 'Expected matching number of modules' ); $this->assertSame( 'Dependent', $modules->current()->getName(), 'Expected first module name to match' ); } /** * Test idExists(). */ public function testIdExists() { $this->assertTrue(P4Cms_Module::exists('Independent')); $this->assertTrue(P4Cms_Module::exists('Dependent')); $this->assertFalse(P4Cms_Module::exists('NonExistant')); } /** * Test getConfig(). */ public function testGetConfig() { P4Cms_Module::fetch('Independent')->enable(); $config = P4Cms_Module::fetch('Independent')->getConfig(); $this->assertTrue($config instanceof Zend_Config); } /** * Test setConfig(). */ public function testSetConfig() { $module = P4Cms_Module::fetch('Independent'); $config = new Zend_Config(array('foo'=>'bar')); $module->setConfig($config); $this->assertTrue($module->getConfig() instanceof Zend_Config); $this->assertTrue($module->getConfig()->foo == 'bar'); } /** * Test saveConfig(). */ public function testSaveConfig() { // test basic usage of save config. $module = P4Cms_Module::fetch('Independent'); $module->saveConfig(new Zend_Config(array('foo'=>'bar'), true)); $module = P4Cms_Module::fetch('Independent'); $this->assertTrue($module->getConfig() instanceof Zend_Config); $this->assertTrue($module->getConfig()->foo == 'bar'); // test usage of save config via set config. $module->setConfig(new Zend_Config(array('baz'=>'bof'), true)); $module->saveConfig(); $module = P4Cms_Module::fetch('Independent'); $this->assertTrue($module->getConfig() instanceof Zend_Config); $this->assertTrue($module->getConfig()->baz == 'bof'); // test save config via reference. $config = $module->getConfig(); $config->zig = 'zag'; $module->saveConfig(); $module = P4Cms_Module::fetch('Independent'); $this->assertTrue($module->getConfig() instanceof Zend_Config); $this->assertTrue($module->getConfig()->zig == 'zag'); } /** * Test isEnabled(). */ public function testIsEnabled() { $module = P4Cms_Module::fetch('Independent'); $this->assertFalse($module->isEnabled()); $module->enable(); $this->assertTrue($module->isEnabled()); $module = P4Cms_Module::fetch('Independent'); $this->assertTrue($module->isEnabled()); } /** * Test canDisable(). */ public function testCanDisable() { $module = P4Cms_Module::fetch('Core'); $this->assertFalse($module->canDisable()); $this->assertTrue($module->isEnabled()); $module = P4Cms_Module::fetch('Independent'); $this->assertFalse($module->canDisable()); $this->assertFalse($module->isEnabled()); $module->enable(); $this->assertTrue($module->canDisable()); $this->assertTrue($module->isEnabled()); // now add known dependent. $dependent = P4Cms_Module::fetch('Dependent')->enable(); $this->assertTrue($dependent->isEnabled()); $this->assertTrue($dependent->canDisable()); $this->assertFalse($module->canDisable()); // remove dependency. $dependent->disable(); $this->assertTrue($module->canDisable()); } /** * Test disabling of modules. */ public function testDisable() { // disable on core module should bork. $module = P4Cms_Module::fetch('Core'); try { $module->disable(); $this->fail("Disable of core module should fail."); } catch (P4Cms_Module_Exception $e) { $this->assertTrue(true); } // disable on disabled module should bork. $module = P4Cms_Module::fetch('Independent'); try { $module->disable(); $this->fail("Disable of disabled module should fail."); } catch (P4Cms_Module_Exception $e) { $this->assertTrue(true); } // now enable so that we can disable. $fluent = $module->enable(); $this->assertTrue($module->isEnabled()); // ensure fluent. $this->assertSame($module, $fluent); // ensure fetches as enabled. $fetched = P4Cms_Module::fetch('Independent'); $this->assertTrue($fetched->isEnabled()); // now test disable. $module->disable(); $this->assertFalse($module->isEnabled()); } /** * Test enabling a disabled module. */ public function testEnable() { $module = P4Cms_Module::fetch('Independent'); $enabledModule = $module->enable(); $this->assertTrue($module->isEnabled()); $this->assertTrue($enabledModule->isEnabled()); $this->assertSame($module, $enabledModule); } /** * Test un-enablable module. */ public function testUnenablable() { $moduleName = 'Unenablable'; $module = P4Cms_Module::fetch($moduleName); try { $module->enable(); $this->fail('Unexpected Success'); } catch (P4Cms_Module_Exception $e) { $this->assertSame( "Failed to enable the 'Unenablable' module.", $e->getMessage(), 'Expected matching error' ); } } /** * Test canEnable. */ public function testCanEnable() { $this->assertSame( false, P4Cms_Module::fetch('Independent')->isEnabled(), 'Expected independent to be disabled' ); $this->assertSame( false, P4Cms_Module::fetch('Dependent')->canEnable(), 'Expected dependent to be disabled' ); $this->assertSame( true, P4Cms_Module::fetch('Independent')->canEnable(), 'Expected to be able to enable module.' ); } /** * Test module initialization. */ public function testInit() { // add another modules path to hit a different 'independent' module. P4Cms_Module::addPackagesPath(TEST_ASSETS_PATH . DIRECTORY_SEPARATOR . 'more-optional-modules'); // enable will call init. $module = P4Cms_Module::fetch('Independent')->enable(); // ensure module was added to loader. $foundPath = false; foreach (P4Cms_Loader::getPackagePaths() as $name => $path) { if ($name == $module->getName() && $path == $module->getPath()) { $foundPath = true; } } $this->assertTrue( $foundPath, "Failed to find Independent in enabled modules" ); // ensure module controllers are added to front controller. $dir = Zend_Controller_Front::getInstance()->getControllerDirectory(basename($module->getPath())); $this->assertFalse(empty($dir)); // ensure module layouts added to view. $foundPath = false; $view = Zend_Layout::getMvcInstance()->getView(); foreach ($view->getScriptPaths() as $path) { if ($path == $module->getPath() . '/layouts/scripts/') { $foundPath = true; } } $this->assertTrue($foundPath, "Independent should have an enabled layout"); // ensure form plugins paths are registered. P4Cms_Module::fetch('Core')->init(); $prefixPaths = P4Cms_Form::getPrefixPathRegistry(); $this->assertTrue( array_key_exists('Core_Form_Element', $prefixPaths), "Expected 'Core_Form_Element' prefix path to be registered." ); } /** * Test module loading. */ public function testLoad() { // enable and load a module. $module = P4Cms_Module::fetch('Independent')->enable(); $module->load(); // ensure all dojo modules are added to dojo. $view = P4Cms_Module::getView(); $dojoModules = $module->getDojoModules(); foreach ($dojoModules as $dojoModule) { $suppliedName = $dojoModule['namespace']; $suppliedUrl = $dojoModule['path']; $foundModule = false; foreach ($view->dojo()->getModulePaths() as $foundName => $foundUrl) { if ($suppliedName == $foundName && $suppliedUrl == $foundUrl) { $foundModule = true; } } $this->assertTrue( $foundModule, "Failed to find module '$suppliedName' in enabled dojo modules" ); } // ensure all routes are added to the router. $router = Zend_Controller_Front::getInstance()->getRouter(); $routes = $module->getRoutes(); foreach ($routes as $name => $route) { $this->assertTrue($router->hasRoute($name), "Failed to hasRoute"); $this->assertEquals( get_class($router->getRoute($name)), $route['type'], "Failed to match route type" ); $this->assertEquals( $router->getRoute($name)->getDefaults(), $route['defaults'], "Failed to match route defaults" ); $this->assertTrue( $router->getRoute($name)->match($route['route']) !== false, "Expected route regex to be a 'match'" ); } } /** * Test module dependencies. */ public function testDependencies() { // dependent module should report dependencies. $this->assertTrue(P4Cms_Module::fetch('Dependent')->hasDependencies()); // dependent module should have two dependencies // one module and one library. $dependencies = array( array( 'name' => 'P4Cms', 'type' => 'library', 'versions' => array('1.*') ), array( 'name' => 'Independent', 'type' => 'module', 'versions' => array('*') ) ); $this->assertSame( $dependencies, P4Cms_Module::fetch('Dependent')->getDependencies(), "Expected matching dependencies array." ); // independent module should report no dependencies. $this->assertFalse(P4Cms_Module::fetch('Independent')->hasDependencies()); // test dependency satisfaction code. $module = P4Cms_Module::fetch('Dependent'); $this->assertFalse( $module->areDependenciesSatisfied(), "Dependent module should have missing dependencies." ); P4Cms_Module::fetch('Independent')->enable(); $this->assertTrue( $module->areDependenciesSatisfied(), "Dependent module should have all dependencies." ); $module->enable(); // test arbitrary dependencies. $tests = array( array( "name" => "FooModule", "type" => "module", "versions" => "*", "expected" => false, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => "*", "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => "1.0", "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => "2.0", "expected" => false, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => "0.9", "expected" => false, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => array("1.0", "2.0", "3.0"), "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => array("0.1", "2.0", "1.0.beta"), "expected" => false, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => array("1.*"), "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => array("1.?"), "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => array("1?", "2.*"), "expected" => false, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => array("1.[0245]", "2.*"), "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "Dependent", "type" => "module", "versions" => array("1.0*"), "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "P4Cms", "type" => "library", "versions" => array("1.0*"), "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "P4Cms", "type" => "library", "versions" => array("1.1"), "expected" => false, "label" => __LINE__ . " unexpected result." ), array( "name" => "Zend", "type" => "library", "versions" => array("1.*"), "expected" => true, "label" => __LINE__ . " unexpected result." ), array( "name" => "FooBar", "type" => "library", "versions" => array("1.0*"), "expected" => false, "label" => __LINE__ . " unexpected result." ), ); foreach ($tests as $test) { $this->assertSame( $test['expected'], P4Cms_Module::isDependencySatisfied( $test['name'], $test['type'], $test['versions'] ), $test['label'] ); } } /** * Test hasDependents(). */ public function testHasDependents() { // test module with no dependents. $module = P4Cms_Module::fetch('Independent')->enable(); $this->assertFalse($module->hasDependents()); // enable a known dependent. P4Cms_Module::fetch('Dependent')->enable(); $this->assertTrue($module->hasDependents()); } /** * Test missing dependency enable. */ public function testMissingDependencyEnable() { $moduleName = 'Dependent'; $module = P4Cms_Module::fetch($moduleName); try { $module->enable(); $this->fail('Unexpected Success'); } catch (P4Cms_Module_Exception $e) { $this->assertSame( "Can't enable the '" . $moduleName . "' module. One or more dependencies are not satisfied.", $e->getMessage(), 'Expected matching error' ); } } /** * Test getIntegrationClassName(). */ public function testIntegrationClassName() { $module = P4Cms_Module::fetch('Independent'); $this->assertSame($module->getIntegrationClassName(), 'Independent_Module'); $module = P4Cms_Module::fetch('Dependent'); $this->assertSame($module->getIntegrationClassName(), 'Dependent_Module'); } /** * Test hasIntegrationClass(). */ public function testHasIntegrationClass() { // add another modules path to hit a different 'independent' module. P4Cms_Module::addPackagesPath(TEST_ASSETS_PATH . '/more-optional-modules'); $module = P4Cms_Module::fetch('Independent')->enable(); $this->assertTrue($module->hasIntegrationClass()); $module = P4Cms_Module::fetch('Dependent')->enable(); $this->assertFalse($module->hasIntegrationClass()); } /** * Test callIntegrationMethod(). */ public function testCallIntegrationMethod() { // add another modules path to hit a different 'independent' module. P4Cms_Module::addPackagesPath(TEST_ASSETS_PATH . '/more-optional-modules'); $module = P4Cms_Module::fetch('Independent')->enable(); $this->assertTrue($module->callIntegrationMethod('load')); $input = array('a','b','c'); $output = $module->callIntegrationMethod('returnInput', array($input)); $this->assertTrue($output == $input); } /** * Test isConfigurable(). */ public function testIsConfigurable() { // add another modules path to hit a different 'independent' module. P4Cms_Module::addPackagesPath(TEST_ASSETS_PATH . '/more-optional-modules'); $module = P4Cms_Module::fetch('Independent')->enable(); $this->assertTrue($module->isConfigurable()); $module = P4Cms_Module::fetch('Dependent')->enable(); $this->assertFalse($module->isConfigurable()); } /** * Test order of module paths. */ public function testModulePathsPrecedence() { $module = P4Cms_Module::fetch('Core'); $this->assertSame($module->getPath(), $module->getCoreModulesPath() . DIRECTORY_SEPARATOR . 'core'); } /** * Test module-provided view helpers. */ public function testModuleViewHelper() { // add p4cms library helpers to a view. $view = new Zend_View; $view->addHelperPath( LIBRARY_PATH . '/P4Cms/View/Helper/', 'P4Cms_View_Helper_' ); $helper = $view->getHelper('module'); // ensure disabled modules can't be fetched via helper. try { $helper->module('Independent'); $this->fail("Should not be able to get disabled module via helper."); } catch (P4Cms_Module_Exception $e) { $this->assertTrue(true); } $module = P4Cms_Module::fetch('Independent')->enable(); $helper = $view->getHelper('module'); $this->assertTrue($helper instanceof P4Cms_View_Helper_Module); $this->assertTrue($helper->module('Independent') instanceof P4Cms_Module); } }