From c79aafa47da439f9d5cf569dfadbd3b72f60db37 Mon Sep 17 00:00:00 2001 From: Stanislau Komar Date: Wed, 18 Jan 2023 05:26:02 +0400 Subject: [PATCH] v1.6.0 - implements tests and CI --- .gitattributes | 9 ++ .github/workflows/.editorconfig | 2 + .github/workflows/ci.yaml | 48 ++++++ .gitignore | 8 +- .php-cs-fixer.dist.php | 30 ++++ LICENSE | 0 README.md | 3 + composer.json | 62 ++++++-- phpcs.xml | 0 phpstan.neon.dist | 4 + phpunit.xml.dist | 32 ++++ psalm.xml | 17 +++ src/AppKernel.php | 138 +++++++++-------- src/AppKernelInterface.php | 22 ++- src/Business/AbstractActionProcessor.php | 9 ++ src/Business/Event/ApplicationReadyEvent.php | 26 ++-- .../Event/ApplicationTerminatedEvent.php | 10 +- .../KernelActionProcessorInterface.php | 14 +- src/Business/KernelRunActionProcessor.php | 15 +- .../KernelTerminateActionProcessor.php | 10 +- .../Processor/AbstractEmitEventProcessor.php | 17 ++- .../Processor/AppCreateEventRunSuccess.php | 9 ++ .../Processor/AppCreateEventTerminate.php | 9 ++ .../Processor/ProvideKernelProcessor.php | 15 +- tests/Unit/AppKernelTest.php | 143 ++++++++++++++++++ .../Event/ApplicationReadyEventTest.php | 47 ++++++ 26 files changed, 577 insertions(+), 122 deletions(-) create mode 100644 .gitattributes create mode 100644 .github/workflows/.editorconfig create mode 100644 .github/workflows/ci.yaml create mode 100644 .php-cs-fixer.dist.php mode change 100644 => 100755 LICENSE create mode 100644 README.md mode change 100644 => 100755 composer.json mode change 100644 => 100755 phpcs.xml create mode 100644 phpstan.neon.dist create mode 100644 phpunit.xml.dist create mode 100644 psalm.xml create mode 100644 tests/Unit/AppKernelTest.php create mode 100644 tests/Unit/Business/Event/ApplicationReadyEventTest.php diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1366148 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +/.github export-ignore +/tests export-ignore +/phpunit.xml.dist export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.php-cs-fixer.dist.php export-ignore +/psalm.xml export-ignore + +*.php diff=php \ No newline at end of file diff --git a/.github/workflows/.editorconfig b/.github/workflows/.editorconfig new file mode 100644 index 0000000..473df25 --- /dev/null +++ b/.github/workflows/.editorconfig @@ -0,0 +1,2 @@ +[{*.yaml,*.yml}] +indent_size = 2 \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..fe23261 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,48 @@ +name: Plugin CI +on: + push: + branches: [ 'master' ] + pull_request: + +env: + PHP_CS_FIXER_IGNORE_ENV: 1 + XDEBUG_MODE: coverage + +jobs: + tests: + name: "Tests ${{ matrix.php-version }} deps ${{ matrix.dependency-versions }}" + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + # normal, highest, non-dev installs + php-version: [ '8.2' ] + dependency-versions: [ 'highest' ] + include: + # testing lowest PHP version with the lowest dependencies + # - php-version: '8.2' + # dependency-versions: 'lowest' + + # testing dev versions with the highest PHP + - php-version: '8.2' + dependency-versions: 'highest' + + steps: + - name: "Checkout code" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + + - name: "Composer install" + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "${{ matrix.dependency-versions }}" + composer-options: "--prefer-dist --no-progress" + + - name: Run tests + run: composer run test \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3d7e132..c40cd9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ -vendor/ +.idea +vendor composer.lock .phpunit.result.cache +.php-cs-fixer.cache +test-coverage-report +phpunit.xml +.php-cs-fixer.php +phpstan.neon \ No newline at end of file diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..ded2263 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,30 @@ +in(__DIR__.'/src') + ->in(__DIR__.'/tests') +; + +return (new PhpCsFixer\Config()) + ->setRules(array( + '@Symfony' => true, + '@Symfony:risky' => true, + 'protected_to_private' => false, + 'semicolon_after_instruction' => false, + 'header_comment' => [ + 'header' => << + + For the full copyright and license information, please view the LICENSE + file that was distributed with this source code. +EOF + ] + )) + ->setRiskyAllowed(true) + ->setFinder($finder); \ No newline at end of file diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md new file mode 100644 index 0000000..cba81fa --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Micro Framework - The minimum kernel for application initialization. + +Documentation is available [here](https://micro-php.net/docs). If not, we will be grateful if you can become its author :) \ No newline at end of file diff --git a/composer.json b/composer.json old mode 100644 new mode 100755 index eedd755..1570d82 --- a/composer.json +++ b/composer.json @@ -1,13 +1,8 @@ { "name": "micro/kernel-app", "description": "Micro Framework: App Kernel component", - "type": "library", "license": "MIT", - "autoload": { - "psr-4": { - "Micro\\Kernel\\App\\": "src/" - } - }, + "type": "library", "authors": [ { "name": "Stanislau.Komar", @@ -15,11 +10,56 @@ } ], "require": { - "micro/kernel": "^1", "micro/deprecation-supports": "^1", - "micro/plugin-event-emitter": "^1", - "micro/kernel-boot-dependency": "^1", + "micro/kernel": "^1.6", "micro/kernel-boot-configuration": "^1", - "micro/kernel-boot-plugin-depended": "^1" + "micro/kernel-boot-dependency": "^1", + "micro/kernel-boot-plugin-depended": "^1", + "micro/plugin-event-emitter": "^1", + "micro/plugin-locator": "^1" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.29", + "friendsofphp/php-cs-fixer": "^3.13", + "phpstan/phpstan": "^1.9", + "phpunit/php-code-coverage": "^9.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.2" + }, + "autoload": { + "psr-4": { + "Micro\\Kernel\\App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Micro\\Kernel\\App\\Test\\Unit\\": "tests/Unit" + } + }, + "config": { + "allow-plugins": { + "ergebnis/composer-normalize": true + }, + "sort-packages": true + }, + "scripts": { + "coverage": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-text", + "coverage-html": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-html ./test-coverage-report", + "php-cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer fix --verbose --using-cache=no", + "php-cs-try": "PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer fix --verbose --dry-run --using-cache=no", + "phpstan": "./vendor/bin/phpstan analyze --no-progress", + "phpunit": "./vendor/bin/phpunit", + "psalm": "./vendor/bin/psalm --no-progress --show-info=true --no-cache", + "statics": [ + "@phpstan", + "@psalm", + "@php-cs-try" + ], + "test": [ + "@statics", + "composer validate --strict", + "composer normalize", + "@coverage" + ] } -} +} \ No newline at end of file diff --git a/phpcs.xml b/phpcs.xml old mode 100644 new mode 100755 diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..18d77f7 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,4 @@ +parameters: + level: 7 + paths: + - src \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..772dff2 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,32 @@ + + + + + + + + + tests/Unit + + + + + src/ + + + + + src + + + + + + \ No newline at end of file diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..99ad2c8 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/AppKernel.php b/src/AppKernel.php index 496dae3..1fbbbd4 100644 --- a/src/AppKernel.php +++ b/src/AppKernel.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App; use Micro\Component\DependencyInjection\Container; @@ -7,8 +16,6 @@ use Micro\Framework\Kernel\Boot\DependedPluginsBootLoader; use Micro\Framework\Kernel\Boot\DependencyProviderBootLoader; use Micro\Framework\Kernel\Configuration\ApplicationConfigurationInterface; -use Micro\Framework\Kernel\Container\ApplicationContainerFactoryInterface; -use Micro\Framework\Kernel\Container\Impl\ApplicationContainerFactory; use Micro\Framework\Kernel\KernelBuilder; use Micro\Framework\Kernel\KernelInterface; use Micro\Framework\Kernel\Plugin\PluginBootLoaderInterface; @@ -16,38 +23,33 @@ use Micro\Kernel\App\Business\KernelRunActionProcessor; use Micro\Kernel\App\Business\KernelTerminateActionProcessor; use Micro\Plugin\EventEmitter\EventEmitterPlugin; -use Psr\Container\ContainerInterface; +use Micro\Plugin\Locator\LocatorPlugin; class AppKernel implements AppKernelInterface { - /** - * @var KernelInterface - */ - private KernelInterface $kernel; + private bool $isTerminated; - /** - * @var ContainerInterface|null - */ - private ?ContainerInterface $container; + private bool $isStarted; + + private ?KernelInterface $kernel; /** * @var PluginBootLoaderInterface[] */ - private iterable $additionalBootLoaders = []; + private array $additionalBootLoaders = []; /** - * @param ApplicationConfigurationInterface|array $configuration - * @param array $plugins - * @param string $environment + * @param ApplicationConfigurationInterface|array $configuration + * @param class-string[] $plugins */ public function __construct( - private ApplicationConfigurationInterface|array $configuration = [], + private readonly ApplicationConfigurationInterface|array $configuration = [], private array $plugins = [], private readonly string $environment = 'dev' - ) - { - $this->container = $this->createApplicationContainerFactory()->create(); - $this->kernel = $this->createKernel(); + ) { + $this->kernel = null; + $this->isTerminated = false; + $this->isStarted = false; } /** @@ -55,15 +57,15 @@ public function __construct( */ public function container(): Container { - return $this->kernel->container(); + return $this->kernel()->container(); } /** * {@inheritDoc} */ - public function plugins(string $interfaceInherited = null): iterable + public function plugins(string $interfaceInherited = null): \Traversable { - return $this->kernel->plugins($interfaceInherited); + return $this->kernel()->plugins($interfaceInherited); } /** @@ -71,9 +73,17 @@ public function plugins(string $interfaceInherited = null): iterable */ public function run(): void { + if ($this->isStarted) { + return; + } + + $this->kernel = $this->createKernel(); + $this->kernel->run(); $this->createInitActionProcessor()->process($this); + + $this->isStarted = true; } /** @@ -81,9 +91,13 @@ public function run(): void */ public function terminate(): void { + if ($this->isTerminated || !$this->isStarted) { + return; + } + $this->createTerminateActionProcessor()->process($this); - $this->kernel->terminate(); + $this->isTerminated = true; } /** @@ -99,13 +113,11 @@ public function environment(): string */ public function isDevMode(): bool { - return $this->environment() === 'dev'; + return str_starts_with($this->environment(), 'dev'); } /** - * @param PluginBootLoaderInterface $pluginBootLoader - * - * @return $this + * {@inheritDoc} */ public function addBootLoader(PluginBootLoaderInterface $pluginBootLoader): self { @@ -119,50 +131,59 @@ public function addBootLoader(PluginBootLoaderInterface $pluginBootLoader): self */ public function loadPlugin(string $applicationPluginClass): void { - $this->kernel->loadPlugin($applicationPluginClass); + $this->kernel()->loadPlugin($applicationPluginClass); } - /** - * @return KernelInterface - */ protected function createKernel(): KernelInterface { - $kernel = $this + $container = new Container(); + $plugins = $this->plugins; + $this->plugins = []; + + return $this ->createKernelBuilder() - ->addBootLoaders($this->createBootLoaderCollection()) - ->setContainer($this->container) - ->setApplicationPlugins( - [ + ->setContainer($container) + ->addBootLoaders($this->createBootLoaderCollection($container)) + ->setApplicationPlugins(array_unique([ EventEmitterPlugin::class, - ...$this->plugins - ] + LocatorPlugin::class, + ...$plugins, + ]) ) ->build(); + } - $this->container = null; - - return $kernel; + protected function kernel(): KernelInterface + { + if (!$this->kernel) { + $trace = debug_backtrace(); + $caller = $trace[1]; + /** + * @var string $cc + * + * @phpstan-ignore-next-line + * + * @psalm-suppress PossiblyUndefinedArrayOffset + */ + $cc = $caller['class']; + $cm = $caller['function']; + + throw new \RuntimeException(sprintf('Method %s::%s can not be called before %s::run() execution.', $cc, $cm, KernelInterface::class)); + } + + return $this->kernel; } - /** - * @return KernelBuilder - */ protected function createKernelBuilder(): KernelBuilder { return new KernelBuilder(); } - /** - * @return KernelActionProcessorInterface - */ protected function createInitActionProcessor(): KernelActionProcessorInterface { return new KernelRunActionProcessor(); } - /** - * @return KernelActionProcessorInterface - */ protected function createTerminateActionProcessor(): KernelActionProcessorInterface { return new KernelTerminateActionProcessor(); @@ -171,24 +192,17 @@ protected function createTerminateActionProcessor(): KernelActionProcessorInterf /** * @return PluginBootLoaderInterface[] */ - protected function createBootLoaderCollection(): array + protected function createBootLoaderCollection(Container $container): array { $bl = $this->additionalBootLoaders; + $this->additionalBootLoaders = []; return [ new ConfigurationProviderBootLoader($this->configuration), - new DependencyProviderBootLoader($this->container), + new DependencyProviderBootLoader($container), new DependedPluginsBootLoader($this), - ...$bl + ...$bl, ]; } - - /** - * @return ApplicationContainerFactoryInterface - */ - protected function createApplicationContainerFactory(): ApplicationContainerFactoryInterface - { - return new ApplicationContainerFactory(); - } } diff --git a/src/AppKernelInterface.php b/src/AppKernelInterface.php index d9a196a..dedbac5 100644 --- a/src/AppKernelInterface.php +++ b/src/AppKernelInterface.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App; use Micro\Framework\Kernel\KernelInterface; @@ -60,20 +69,17 @@ */ interface AppKernelInterface extends KernelInterface { - /** - * @return string - */ public function environment(): string; - /** - * @return bool - */ public function isDevMode(): bool; /** - * @param PluginBootLoaderInterface $pluginBootLoader - * * @return $this */ public function addBootLoader(PluginBootLoaderInterface $pluginBootLoader): self; + + /** + * Microkernel\App\Business\Event\Application Terminated Event will be fired. + */ + public function terminate(): void; } diff --git a/src/Business/AbstractActionProcessor.php b/src/Business/AbstractActionProcessor.php index 3774566..b05ee01 100644 --- a/src/Business/AbstractActionProcessor.php +++ b/src/Business/AbstractActionProcessor.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business; use Micro\Kernel\App\AppKernelInterface; diff --git a/src/Business/Event/ApplicationReadyEvent.php b/src/Business/Event/ApplicationReadyEvent.php index 899570c..09ef819 100644 --- a/src/Business/Event/ApplicationReadyEvent.php +++ b/src/Business/Event/ApplicationReadyEvent.php @@ -1,41 +1,37 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business\Event; use Micro\Component\EventEmitter\EventInterface; use Micro\Kernel\App\AppKernelInterface; -class ApplicationReadyEvent implements EventInterface +readonly class ApplicationReadyEvent implements EventInterface { - /** - * @param AppKernelInterface $appKernel - * @param string $environment - */ public function __construct(private AppKernelInterface $appKernel, private string $environment) { } - /** - * @return AppKernelInterface - */ public function kernel(): AppKernelInterface { return $this->appKernel; } - /** - * @return string - */ public function environment(): string { return $this->environment; } - /** - * @return string - */ public function systemEnvironment(): string { - return PHP_SAPI; + return \PHP_SAPI; } } diff --git a/src/Business/Event/ApplicationTerminatedEvent.php b/src/Business/Event/ApplicationTerminatedEvent.php index 46ed9bc..7ae8e9b 100644 --- a/src/Business/Event/ApplicationTerminatedEvent.php +++ b/src/Business/Event/ApplicationTerminatedEvent.php @@ -1,10 +1,18 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business\Event; use Micro\Component\EventEmitter\EventInterface; class ApplicationTerminatedEvent implements EventInterface { - } diff --git a/src/Business/KernelActionProcessorInterface.php b/src/Business/KernelActionProcessorInterface.php index 4c95c52..09d44e5 100644 --- a/src/Business/KernelActionProcessorInterface.php +++ b/src/Business/KernelActionProcessorInterface.php @@ -1,15 +1,19 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business; -use Micro\Framework\Kernel\KernelInterface; use Micro\Kernel\App\AppKernelInterface; interface KernelActionProcessorInterface { - /** - * @param AppKernelInterface $appKernel - * @return void - */ public function process(AppKernelInterface $appKernel): void; } diff --git a/src/Business/KernelRunActionProcessor.php b/src/Business/KernelRunActionProcessor.php index be3041a..527651f 100644 --- a/src/Business/KernelRunActionProcessor.php +++ b/src/Business/KernelRunActionProcessor.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business; use Micro\Kernel\App\Business\Processor\AppCreateEventRunSuccess; @@ -18,17 +27,11 @@ protected function createActionProcessorCollection(): array ]; } - /** - * @return KernelActionProcessorInterface - */ protected function createAppCreateEventRunSuccess(): KernelActionProcessorInterface { return new AppCreateEventRunSuccess(); } - /** - * @return KernelActionProcessorInterface - */ protected function createProvideKernelProcessor(): KernelActionProcessorInterface { return new ProvideKernelProcessor(); diff --git a/src/Business/KernelTerminateActionProcessor.php b/src/Business/KernelTerminateActionProcessor.php index 0dd84e6..11e72b5 100644 --- a/src/Business/KernelTerminateActionProcessor.php +++ b/src/Business/KernelTerminateActionProcessor.php @@ -1,8 +1,16 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business; -use Micro\Kernel\App\AppKernelInterface; use Micro\Kernel\App\Business\Processor\AppCreateEventTerminate; class KernelTerminateActionProcessor extends AbstractActionProcessor diff --git a/src/Business/Processor/AbstractEmitEventProcessor.php b/src/Business/Processor/AbstractEmitEventProcessor.php index 02d67f4..64251d8 100644 --- a/src/Business/Processor/AbstractEmitEventProcessor.php +++ b/src/Business/Processor/AbstractEmitEventProcessor.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business\Processor; use Micro\Component\DependencyInjection\Container; @@ -20,20 +29,14 @@ public function process(AppKernelInterface $appKernel): void $this->lookupEventEmitter($appKernel->container())->emit($event); } - /** - * @param AppKernelInterface $appKernel - * @return EventInterface - */ abstract protected function createEvent(AppKernelInterface $appKernel): EventInterface; /** - * @param Container $container - * @return EventsFacadeInterface * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface */ protected function lookupEventEmitter(Container $container): EventsFacadeInterface { - return $container->get(EventsFacadeInterface::class); + return $container->get(EventsFacadeInterface::class); // @phpstan-ignore-line } } diff --git a/src/Business/Processor/AppCreateEventRunSuccess.php b/src/Business/Processor/AppCreateEventRunSuccess.php index edf0e92..1b8fcc0 100644 --- a/src/Business/Processor/AppCreateEventRunSuccess.php +++ b/src/Business/Processor/AppCreateEventRunSuccess.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business\Processor; use Micro\Component\EventEmitter\EventInterface; diff --git a/src/Business/Processor/AppCreateEventTerminate.php b/src/Business/Processor/AppCreateEventTerminate.php index 74a77c8..8ea6ef4 100644 --- a/src/Business/Processor/AppCreateEventTerminate.php +++ b/src/Business/Processor/AppCreateEventTerminate.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business\Processor; use Micro\Component\EventEmitter\EventInterface; diff --git a/src/Business/Processor/ProvideKernelProcessor.php b/src/Business/Processor/ProvideKernelProcessor.php index 6276b0f..41e8d5e 100644 --- a/src/Business/Processor/ProvideKernelProcessor.php +++ b/src/Business/Processor/ProvideKernelProcessor.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Micro\Kernel\App\Business\Processor; use Micro\Framework\Kernel\KernelInterface; @@ -8,13 +17,9 @@ class ProvideKernelProcessor implements KernelActionProcessorInterface { - /** - * @param AppKernelInterface $appKernel - * @return void - */ public function process(AppKernelInterface $appKernel): void { - $callback = fn() => $appKernel; + $callback = fn (): KernelInterface => $appKernel; $appKernel->container()->register(AppKernelInterface::class, $callback); $appKernel->container()->register(KernelInterface::class, $callback); diff --git a/tests/Unit/AppKernelTest.php b/tests/Unit/AppKernelTest.php new file mode 100644 index 0000000..3ade64e --- /dev/null +++ b/tests/Unit/AppKernelTest.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Micro\Kernel\App\Test\Unit; + +use Micro\Component\DependencyInjection\Container; +use Micro\Framework\Kernel\KernelInterface; +use Micro\Framework\Kernel\Plugin\PluginBootLoaderInterface; +use Micro\Kernel\App\AppKernel; +use PHPUnit\Framework\TestCase; + +class AppKernelTest extends TestCase +{ + private AppKernel $kernel; + + protected function setUp(): void + { + $this->kernel = $this->getMockBuilder(AppKernel::class) + ->enableOriginalConstructor() + ->setConstructorArgs([[ + ], [\stdClass::class], 'dev']) + ->onlyMethods([ + 'createBootLoaderCollection', + 'createInitActionProcessor', + 'createTerminateActionProcessor', + ]) + ->getMock() + ; + } + + public function testAppKernel() + { + $app = new AppKernel(); + + $this->assertInstanceOf(KernelInterface::class, $app); + + $app->run(); + + $this->assertInstanceOf(Container::class, $app->container()); + + $app->terminate(); + } + + public function testAddBootLoader() + { + $bootLoader = $this->createMock(PluginBootLoaderInterface::class); + $bootLoader + ->method('boot'); + + $app = new AppKernel([], []); + $appReturn = $app->addBootLoader($bootLoader); + + $this->assertEquals($app, $appReturn); + + $app->run(); + } + + public function testLoadPlugin() + { + $pk = $this->createMock(KernelInterface::class); + $pk->expects($this->once()) + ->method('loadPlugin') + ->with('test_plugin'); + + $app = $this->getMockBuilder(AppKernel::class) + ->enableOriginalConstructor() + ->onlyMethods(['kernel']) + ->getMock() + ; + + $app + ->expects($this->once()) + ->method('kernel') + ->willReturn($pk); + + $app->loadPlugin('test_plugin'); + } + + public function testKernelFail() + { + $app = new AppKernel(); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Method Micro\Kernel\App\AppKernel::plugins can not be called before Micro\Framework\Kernel\KernelInterface::run() execution.'); + + $this->assertNotNull($app->plugins()); + } + + public function testTerminate() + { + $this->kernel + ->expects($this->once()) + ->method('createTerminateActionProcessor'); + + $this->kernel + ->expects($this->once()) + ->method('createInitActionProcessor'); + + $this->kernel->terminate(); + $this->kernel->run(); + $this->kernel->run(); + $this->kernel->terminate(); + } + + /** + * @dataProvider dataProviderIsDevMode + */ + public function testIsDevMode(string $env, bool $isDev) + { + $app = new AppKernel( + [], + [], + $env + ); + + $app->run(); + + $this->assertEquals($isDev, $app->isDevMode()); + $this->assertEquals($app->environment(), $env); + } + + public function dataProviderIsDevMode() + { + return [ + ['dev', true], + ['dev-', true], + ['devel', true], + ['develop', true], + ['test', false], + ['test-dev', false], + ]; + } +} diff --git a/tests/Unit/Business/Event/ApplicationReadyEventTest.php b/tests/Unit/Business/Event/ApplicationReadyEventTest.php new file mode 100644 index 0000000..12fefc9 --- /dev/null +++ b/tests/Unit/Business/Event/ApplicationReadyEventTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Micro\Kernel\App\Test\Unit\Business\Event; + +use Micro\Kernel\App\AppKernelInterface; +use Micro\Kernel\App\Business\Event\ApplicationReadyEvent; +use PHPUnit\Framework\TestCase; + +class ApplicationReadyEventTest extends TestCase +{ + private ApplicationReadyEvent $evt; + + private AppKernelInterface $kernel; + + protected function setUp(): void + { + $this->kernel = $this->createMock(AppKernelInterface::class); + + $this->evt = new ApplicationReadyEvent($this->kernel, 'dev'); + } + + public function testEnvironment() + { + $this->assertEquals('dev', $this->evt->environment()); + } + + public function testSystemEnvironment() + { + $this->assertEquals(\PHP_SAPI, $this->evt->systemEnvironment()); + } + + public function testKernel() + { + $this->assertEquals($this->kernel, $this->evt->kernel()); + } +}