ModuleTest.php #1

  • //
  • guest/
  • perforce_software/
  • chronicle/
  • main/
  • tests/
  • phpunit/
  • P4Cms/
  • ModuleTest.php
  • View
  • Commits
  • Open Download .zip Download (25 KB)
<?php
/**
 * Test the module model.
 *
 * @copyright   2011 Perforce Software. All rights reserved.
 * @license     Please see LICENSE.txt in top-level folder of this distribution.
 * @version     <release>/<patch>
 */
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);
    }
}
# Change User Description Committed
#1 16170 perforce_software Move Chronicle files to follow new path scheme for branching.
//guest/perforce_software/chronicle/tests/phpunit/P4Cms/ModuleTest.php
#1 8972 Matt Attaway Initial add of the Chronicle source code