Skip to content

Commit

Permalink
Refactor ContainerProvider for unit tests
Browse files Browse the repository at this point in the history
Replace explicit third-party service definitions with third-party service providers.

This resolves issues stemming from third-party dependencies expecting internal or optional dependencies to be present.

Examples:
- "module/classes" is a feature from charcoal-app that is supported by charcoal-view and charcoal-core but unnecessary for charcoal-ui.
- Zend Framework is in transition to become Laminas; zend-permissions-acl / laminas-permissions-acl is required by charcoal-user but incidental for charcoal-ui.
  • Loading branch information
mcaskill committed Feb 11, 2020
1 parent fcffd20 commit f79402a
Show file tree
Hide file tree
Showing 12 changed files with 68 additions and 228 deletions.
7 changes: 3 additions & 4 deletions tests/Charcoal/Ui/ContainerIntegrationTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,10 @@ private function setupContainer()
$container = new Container();

$provider->registerBaseServices($container);
$provider->registerViewServices($container);
$provider->registerModelServices($container);
$provider->registerAuthServices($container);
$provider->registerTranslator($container);
$provider->registerMetadataLoader($container);
$provider->registerSourceFactory($container);
$provider->registerPropertyFactory($container);
$provider->registerTranslatorServices($container);

$this->container = $container;
$this->containerProvider = $provider;
Expand Down
257 changes: 64 additions & 193 deletions tests/Charcoal/Ui/ContainerProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,24 @@
// From PSR-3
use Psr\Log\NullLogger;

// From 'cache/void-adapter' (PSR-6)
use Cache\Adapter\Void\VoidCachePool;

// From 'tedivm/stash' (PSR-6)
use Stash\Pool;
use Stash\Driver\Ephemeral;

// From 'zendframework/zend-permissions-acl'
use Zend\Permissions\Acl\Acl;

// From Pimple
use Pimple\Container;

// From 'charcoal-factory'
use Charcoal\Factory\GenericFactory as Factory;

// From 'charcoal-core'
use Charcoal\Model\Service\MetadataLoader;
use Charcoal\Loader\CollectionLoader;
use Charcoal\Source\DatabaseSource;
use Charcoal\Model\ServiceProvider\ModelServiceProvider;

// From 'charcoal-user'
use Charcoal\User\Authenticator;
use Charcoal\User\Authorizer;
use Charcoal\User\ServiceProvider\AuthServiceProvider;

// From 'charcoal-translator'
use Charcoal\Translator\LocalesManager;
use Charcoal\Translator\Translator;
use Charcoal\Translator\ServiceProvider\TranslatorServiceProvider;

// From 'charcoal-view'
use Charcoal\View\GenericView;
use Charcoal\View\Mustache\MustacheEngine;
use Charcoal\View\Mustache\MustacheLoader;
use Charcoal\View\ViewServiceProvider;

/**
* Service Container for Unit Tests
Expand All @@ -54,6 +39,7 @@ class ContainerProvider
*/
public function registerBaseServices(Container $container)
{
$this->registerConfig($container);
$this->registerSource($container);
$this->registerLogger($container);
$this->registerCache($container);
Expand All @@ -65,10 +51,29 @@ public function registerBaseServices(Container $container)
* @param Container $container A DI container.
* @return void
*/
public function registerAuthServices(Container $container)
public function registerConfig(Container $container)
{
$this->registerAuthenticator($container);
$this->registerAuthorizer($container);
$container['config'] = [
'base_path' => realpath(__DIR__.'/../../..'),
'locales' => [
'en' => [
'locale' => 'en-US',
],
],
'translator' => [
'paths' => [],
],
];

/**
* List of Charcoal module classes.
*
* Explicitly defined in case of a version mismatch with dependencies. This parameter
* is normally defined by {@see \Charcoal\App\ServiceProvider\AppServiceProvider}.
*
* @var array
*/
$container['module/classes'] = [];
}

/**
Expand All @@ -89,230 +94,96 @@ public function registerSource(Container $container)
}

/**
* Setup the application's logging interface.
* Register the admin services.
*
* @param Container $container A DI container.
* @return void
*/
public function registerLogger(Container $container)
public function registerModelServices(Container $container)
{
$container['logger'] = function () {
return new NullLogger();
};
}
static $provider = null;

/**
* Setup the application's caching interface.
*
* @param Container $container A DI container.
* @return void
*/
public function registerCache(Container $container)
{
$container['cache'] = function () {
return new Pool();
};
if ($provider === null) {
$provider = new ModelServiceProvider();
}

$provider->register($container);
}

/**
* Setup the application's translator service.
* Register the admin services.
*
* @param Container $container A DI container.
* @return void
*/
public function registerTranslator(Container $container)
public function registerAuthServices(Container $container)
{
$container['locales/manager'] = function () {
return new LocalesManager([
'locales' => [
'en' => [ 'locale' => 'en-US' ]
]
]);
};
static $provider = null;

$container['translator'] = function (Container $container) {
return new Translator([
'manager' => $container['locales/manager']
]);
};
}
if ($provider === null) {
$provider = new AuthServiceProvider();
}

/**
* Setup the framework's metadata loader interface.
*
* @param Container $container A DI container.
* @return void
*/
public function registerMetadataLoader(Container $container)
{
$container['metadata/loader'] = function (Container $container) {
return new MetadataLoader([
'cache' => $container['cache'],
'logger' => $container['logger'],
'base_path' => realpath(__DIR__.'/../../../'),
'paths' => [
'metadata',
'vendor/locomotivemtl/charcoal-property/metadata'
]
]);
};
$provider->register($container);
}

/**
* Setup the framework's data source factory.
* Setup the application's translator service.
*
* @param Container $container A DI container.
* @return void
*/
public function registerSourceFactory(Container $container)
public function registerTranslatorServices(Container $container)
{
$container['source/factory'] = function ($container) {
return new Factory([
'map' => [
'database' => DatabaseSource::class
],
'arguments' => [[
'logger' => $container['logger'],
'cache' => $container['cache'],
'pdo' => $container['database']
]]
]);
};
}
static $provider = null;

/**
* Setup the framework's model factory.
*
* @param Container $container A DI container.
* @return void
*/
public function registerModelFactory(Container $container)
{
$container['model/factory'] = function ($container) {
return new Factory([
'arguments' => [[
'container' => $container,
'logger' => $container['logger'],
'metadata_loader' => $container['metadata/loader'],
'source_factory' => $container['source/factory'],
'property_factory' => $container['property/factory']
]]
]);
};
}
if ($provider === null) {
$provider = new TranslatorServiceProvider();
}

/**
* Setup the framework's property factory.
*
* @param Container $container A DI container.
* @return void
*/
public function registerPropertyFactory(Container $container)
{
$container['property/factory'] = function (Container $container) {
return new Factory([
'resolver_options' => [
'prefix' => '\\Charcoal\\Property\\',
'suffix' => 'Property'
],
'arguments' => [[
'container' => $container,
'database' => $container['database'],
'logger' => $container['logger'],
'translator' => $container['translator']
]]
]);
};
$provider->register($container);
}

/**
* Setup the framework's collection loader interface.
* Setup the framework's view renderer.
*
* @param Container $container A DI container.
* @return void
*/
public function registerModelCollectionLoader(Container $container)
public function registerViewServices(Container $container)
{
$container['model/collection/loader'] = function (Container $container) {
return new CollectionLoader([
'logger' => $container['logger'],
'cache' => $container['cache']
]);
};
}
static $provider = null;

/**
* Setup the authenticator service.
*
* @param Container $container A DI container.
* @return void
*/
public function registerAuthenticator(Container $container)
{
$this->registerLogger($container);
$this->registerModelFactory($container);
if ($provider === null) {
$provider = new ViewServiceProvider();
}

$container['authenticator'] = function (Container $container) {
return new Authenticator([
'logger' => $container['logger'],
'user_type' => 'charcoal/user',
'user_factory' => $container['model/factory'],
'token_type' => 'charcoal/user/auth-token',
'token_factory' => $container['model/factory']
]);
};
$provider->register($container);
}

/**
* Setup the authorizer service.
* Setup the application's logging interface.
*
* @param Container $container A DI container.
* @return void
*/
public function registerAuthorizer(Container $container)
public function registerLogger(Container $container)
{
$this->registerLogger($container);

$container['authorizer'] = function (Container $container) {
return new Authorizer([
'logger' => $container['logger'],
'acl' => new Acl(),
'resource' => 'test'
]);
$container['logger'] = function () {
return new NullLogger();
};
}

/**
* Setup the framework's view renderer.
* Setup the application's caching interface.
*
* @param Container $container A DI container.
* @return void
*/
public function registerView(Container $container)
public function registerCache(Container $container)
{
$container['view/loader'] = function (Container $container) {
return new MustacheLoader([
'logger' => $container['logger'],
'base_path' => realpath(__DIR__.'/../../../'),
'paths' => [
'views'
]
]);
};

$container['view/engine'] = function (Container $container) {
return new MustacheEngine([
'logger' => $container['logger'],
'cache' => $container['cache'],
'loader' => $container['view/loader']
]);
};

$container['view'] = function (Container $container) {
return new GenericView([
'logger' => $container['logger'],
'engine' => $container['view/engine']
]);
$container['cache'] = function () {
return new Pool();
};
}
}
3 changes: 0 additions & 3 deletions tests/Charcoal/Ui/Dashboard/AbstractDashboardTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ public function setUp()
$container->register(new LayoutServiceProvider());
$container->register(new FormServiceProvider());

$provider = $this->getContainerProvider();
$provider->registerView($container);

$this->obj = $this->getMockForAbstractClass(AbstractDashboard::class, [
[
'logger' => $container['logger'],
Expand Down
3 changes: 0 additions & 3 deletions tests/Charcoal/Ui/Dashboard/GenericDashboardTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ public function setUp()
$container->register(new LayoutServiceProvider());
$container->register(new FormServiceProvider());

$provider = $this->getContainerProvider();
$provider->registerView($container);

$this->obj = new GenericDashboard([
'logger' => $container['logger'],
'view' => $container['view'],
Expand Down
3 changes: 0 additions & 3 deletions tests/Charcoal/Ui/Form/AbstractFormTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ public function setUp()
$container->register(new FormServiceProvider());
$container->register(new LayoutServiceProvider());

$provider = $this->getContainerProvider();
$provider->registerView($container);

$this->obj = $this->getMockForAbstractClass(AbstractForm::class, [
[
'container' => $container,
Expand Down
Loading

0 comments on commit f79402a

Please sign in to comment.