From a2ca85b72a26f20eef108bc3dddbb76ca5f4a64b Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Fri, 7 Jul 2023 14:44:40 +0300 Subject: [PATCH 01/10] Issue #8 #9: Code quality and green badge. Signed-off-by: alexmerlin --- .gitignore | 3 +- README.md | 20 +- composer.json | 28 ++- ...gbar.local.php.dist => debugbar.local.php} | 6 +- phpcs.xml | 21 ++ phpunit.xml | 17 ++ psalm-baseline.xml | 9 + psalm.xml | 18 ++ src/ConfigProvider.php | 17 +- src/DebugBar.php | 88 +++----- src/DebugBarInterface.php | 35 +++ src/Extension/DebugBarExtension.php | 32 +-- src/Factory/DebugBarExtensionFactory.php | 41 +++- src/Factory/DebugBarFactory.php | 49 +++- src/Factory/DebugBarMiddlewareFactory.php | 20 +- src/Middleware/DebugBarMiddleware.php | 55 ++--- .../DebugBarMiddlewareInterface.php | 7 +- test/CommonTrait.php | 18 ++ test/ConfigProviderTest.php | 55 +++++ test/DummyResponse.php | 73 ++++++ test/Extension/DebugBarExtensionTest.php | 130 +++++++++++ test/Factory/DebugBarExtensionFactoryTest.php | 81 +++++++ test/Factory/DebugBarFactoryTest.php | 210 ++++++++++++++++++ .../Factory/DebugBarMiddlewareFactoryTest.php | 83 +++++++ test/Middleware/DebugBarMiddlewareTest.php | 83 +++++++ 25 files changed, 1041 insertions(+), 158 deletions(-) rename config/{debugbar.local.php.dist => debugbar.local.php} (84%) create mode 100644 phpcs.xml create mode 100644 phpunit.xml create mode 100644 psalm-baseline.xml create mode 100644 psalm.xml create mode 100644 src/DebugBarInterface.php create mode 100644 test/CommonTrait.php create mode 100644 test/ConfigProviderTest.php create mode 100644 test/DummyResponse.php create mode 100644 test/Extension/DebugBarExtensionTest.php create mode 100644 test/Factory/DebugBarExtensionFactoryTest.php create mode 100644 test/Factory/DebugBarFactoryTest.php create mode 100644 test/Factory/DebugBarMiddlewareFactoryTest.php create mode 100644 test/Middleware/DebugBarMiddlewareTest.php diff --git a/.gitignore b/.gitignore index 670d08c..178a6df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ clover.xml coveralls-upload.json -phpunit.xml +.phpcs-cache +.phpunit.result.cache # Created by .ignore support plugin (hsz.mobi) ### JetBrains template diff --git a/README.md b/README.md index 77e1be8..da93d69 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,22 @@ DotKernel's debug bar built on top of [maximebf/php-debugbar](https://github.com/maximebf/php-debugbar). ![OSS Lifecycle](https://img.shields.io/osslifecycle/dotkernel/dot-debugbar) +![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-debugbar/1.1.0) [![GitHub issues](https://img.shields.io/github/issues/dotkernel/dot-debugbar)](https://github.com/dotkernel/dot-debugbar/issues) [![GitHub forks](https://img.shields.io/github/forks/dotkernel/dot-debugbar)](https://github.com/dotkernel/dot-debugbar/network) [![GitHub stars](https://img.shields.io/github/stars/dotkernel/dot-debugbar)](https://github.com/dotkernel/dot-debugbar/stargazers) -[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-debugbar)](https://github.com/dotkernel/dot-debugbar/blob/main/LICENSE.md) +[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-debugbar)](https://github.com/dotkernel/dot-debugbar/blob/1.0/LICENSE.md) -![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-debugbar/1.0.x-dev) +[![Build Static](https://github.com/dotkernel/dot-debugbar/actions/workflows/static-analysis.yml/badge.svg?branch=1.0)](https://github.com/dotkernel/dot-debugbar/actions/workflows/static-analysis.yml) + +[![SymfonyInsight](https://insight.symfony.com/projects/c1dc83af-a4b3-4a46-a80c-d87dff782089/big.svg)](https://insight.symfony.com/projects/c1dc83af-a4b3-4a46-a80c-d87dff782089) ## Install Install dot-debugbar in your application by running the following command: -```bash -$ composer require dotkernel/dot-debugbar -``` + + composer require dotkernel/dot-debugbar ## Setup @@ -27,7 +29,7 @@ Once installed, the following components need to be registered by adding: Locate the library's assets directory, called `assets` and copy **its contents** to your application under `public/debugbar` directory. -Locate the library's config file `config/debugbar.local.php.dist` and clone it inside your application as: +Locate the library's config file `config/debugbar.local.php` and clone it inside your application as: * `config/autoload/debugbar.local.php.dist` * `config/autoload/debugbar.local.php` @@ -56,9 +58,9 @@ This feature can be useful if you need to add custom logic for when dot-debugbar Other than the data being automatically collected during a session, dot-debugbar can also be used to log messages, measure durations, debug database queries and more... When you need an instance of DebugBar, locate an instance of it in your application's container using: -```php -$debugBar = $container->get(\Dot\DebugBar\DebugBar::class); -``` + + $debugBar = $container->get(\Dot\DebugBar\DebugBar::class); + then your factory can inject `$debugBar` as a dependency in your class. OR diff --git a/composer.json b/composer.json index 7d42ba7..1ad8a11 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,10 @@ } ], "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } }, "autoload": { "psr-4": { @@ -24,10 +27,31 @@ } }, "require": { - "php": "~7.4.0||~8.0.0||~8.1.0", + "php": "~8.1.0 || ~8.2.0", "doctrine/orm": "^2.7", "dotkernel/dot-twigrenderer": "^3.1", "laminas/laminas-stratigility": "^3.9", "maximebf/debugbar": "^1.17" + }, + "autoload-dev": { + "psr-4": { + "DotTest\\DebugBar\\": "test/" + } + }, + "require-dev": { + "laminas/laminas-coding-standard": "^2.5", + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.13" + }, + "scripts": { + "check": [ + "@cs-check", + "@test" + ], + "cs-check": "phpcs", + "cs-fix": "phpcbf", + "test": "phpunit --colors=always", + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", + "static-analysis": "psalm --shepherd --stats" } } diff --git a/config/debugbar.local.php.dist b/config/debugbar.local.php similarity index 84% rename from config/debugbar.local.php.dist rename to config/debugbar.local.php index 16e0820..a15cc9d 100644 --- a/config/debugbar.local.php.dist +++ b/config/debugbar.local.php @@ -27,9 +27,9 @@ * @see \DebugBar\JavascriptRenderer::setOptions() */ 'javascript_renderer' => [ - 'base_url' => '', - 'base_path' => '', - 'disable_jquery' => false, + 'base_url' => '', + 'base_path' => '', + 'disable_jquery' => false, 'disable_fontawesome' => false, 'disable_highlightjs' => false, ], diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..0d4c1dc --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + config + src + test + + + + diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..555b100 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,17 @@ + + + + + ./test + + + + + + ./src + + + diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 0000000..1efa45c --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,9 @@ + + + + + ErrorResponseGenerator + ErrorResponseGenerator + + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..9dd8f07 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 276fb6f..749985b 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -1,6 +1,6 @@ $this->getDependencyConfig() + 'dependencies' => $this->getDependencyConfig(), ]; } @@ -29,14 +29,15 @@ public function __invoke(): array public function getDependencyConfig(): array { return [ - 'aliases' => [ - DebugBarMiddlewareInterface::class => DebugBarMiddleware::class + 'aliases' => [ + DebugBarInterface::class => DebugBar::class, + DebugBarMiddlewareInterface::class => DebugBarMiddleware::class, ], 'factories' => [ - DebugBar::class => DebugBarFactory::class, - DebugBarExtension::class => DebugBarExtensionFactory::class, - DebugBarMiddleware::class => DebugBarMiddlewareFactory::class - ] + DebugBar::class => DebugBarFactory::class, + DebugBarExtension::class => DebugBarExtensionFactory::class, + DebugBarMiddleware::class => DebugBarMiddlewareFactory::class, + ], ]; } } diff --git a/src/DebugBar.php b/src/DebugBar.php index b8d05aa..ec5b7d5 100644 --- a/src/DebugBar.php +++ b/src/DebugBar.php @@ -1,6 +1,6 @@ getConnection()->getConfiguration()->setSQLLogger($debugStack); + $configuration->setSQLLogger($debugStack); $this->addCollector($this->memoryCollector = new MemoryCollector()); $this->addCollector($this->phpInfoCollector = new PhpInfoCollector()); @@ -52,30 +58,27 @@ public function __construct(EntityManager $entityManager, array $config) $this->addCollector($this->timeDataCollector = new TimeDataCollector()); $this->addCollector($this->exceptionsCollector = new ExceptionsCollector()); - $this->config = $config[DebugBar::class] ?? []; + $this->config = $config[self::class] ?? []; $this->getJavascriptRenderer()->addAssets( [ - 'dotkernel.css' - ], [] + 'dotkernel.css', + ], + [] ); $this->getJavascriptRenderer()->setOptions($this->config['javascript_renderer'] ?? []); - if (!empty($this->config['javascript_renderer']['disable_jquery'])) { + if (! empty($this->config['javascript_renderer']['disable_jquery'])) { $this->getJavascriptRenderer()->disableVendor('jquery'); } - if (!empty($this->config['javascript_renderer']['disable_fontawesome'])) { + if (! empty($this->config['javascript_renderer']['disable_fontawesome'])) { $this->getJavascriptRenderer()->disableVendor('fontawesome'); } - if (!empty($this->config['javascript_renderer']['disable_highlightjs'])) { + if (! empty($this->config['javascript_renderer']['disable_highlightjs'])) { $this->getJavascriptRenderer()->disableVendor('highlightjs'); } } - /** - * @param string $ipAddress - * @return bool - */ public function shouldEnable(string $ipAddress): bool { /** @@ -101,10 +104,6 @@ public function shouldEnable(string $ipAddress): bool } } - /** - * @param string $ipAddress - * @return bool - */ private function shouldEnableIPV4(string $ipAddress): bool { /** @@ -127,10 +126,6 @@ private function shouldEnableIPV4(string $ipAddress): bool return in_array($ipAddress, $this->config['ipv4Whitelist']); } - /** - * @param string $ipAddress - * @return bool - */ private function shouldEnableIPV6(string $ipAddress): bool { /** @@ -153,85 +148,60 @@ private function shouldEnableIPV6(string $ipAddress): bool return in_array($ipAddress, $this->config['ipv6Whitelist']); } - /** - * @return bool - */ public function isEnabled(): bool { return $this->status === self::STATUS_ENABLED; } - /** - * @return $this - */ public function enable(): self { $this->status = self::STATUS_ENABLED; + return $this; } - /** - * @return $this - */ public function disable(): self { $this->status = self::STATUS_DISABLED; + return $this; } - /** - * @param $message - * @param string $label - * @param bool $isString - * @return $this - */ - public function addMessage($message, string $label = 'info', bool $isString = true): self + public function addMessage(mixed $message, string $label = 'info', bool $isString = true): self { $this->messagesCollector->addMessage($message, $label, $isString); + return $this; } - /** - * @param string $name - * @param string|null $label - * @return $this - */ public function startTimer(string $name, ?string $label = null): self { $this->timeDataCollector->startMeasure($name, $label); + return $this; } /** - * @param string $name - * @param array $params - * @return $this - * @throws DebugBarException + * @inheritDoc */ public function stopTimer(string $name, array $params = []): self { $this->timeDataCollector->stopMeasure($name, $params); + return $this; } - /** - * @param string $name - * @param Closure $closure - * @return $this - */ public function measure(string $name, Closure $closure): self { $this->timeDataCollector->measure($name, $closure); + return $this; } - /** - * @param Throwable $throwable - * @return $this - */ public function addThrowable(Throwable $throwable): self { $this->exceptionsCollector->addThrowable($throwable); + return $this; } } diff --git a/src/DebugBarInterface.php b/src/DebugBarInterface.php new file mode 100644 index 0000000..239f3d1 --- /dev/null +++ b/src/DebugBarInterface.php @@ -0,0 +1,35 @@ +config = $config; $this->debugBar = $debugBar; - $this->baseUrl = rtrim($this->config['application']['url'], '/'); + $this->baseUrl = $baseUrl; } /** @@ -40,20 +35,14 @@ public function getFunctions(): array ]; } - /** - * @return bool - */ public function renderDebugBarEnabled(): bool { return $this->debugBar->isEnabled(); } - /** - * @return string|null - */ public function renderDebugBarCss(): ?string { - if (!$this->debugBar->isEnabled()) { + if (! $this->debugBar->isEnabled()) { return null; } @@ -66,12 +55,9 @@ public function renderDebugBarCss(): ?string return $return; } - /** - * @return string|null - */ public function renderDebugBarJs(): ?string { - if (!$this->debugBar->isEnabled()) { + if (! $this->debugBar->isEnabled()) { return null; } diff --git a/src/Factory/DebugBarExtensionFactory.php b/src/Factory/DebugBarExtensionFactory.php index 55c72eb..823352d 100644 --- a/src/Factory/DebugBarExtensionFactory.php +++ b/src/Factory/DebugBarExtensionFactory.php @@ -1,28 +1,57 @@ has('config')) { + throw new Exception(DebugBarFactory::MESSAGE_MISSING_CONFIG); + } + + if (! $container->has(DebugBarInterface::class)) { + throw new Exception(DebugBarFactory::MESSAGE_MISSING_DEBUG_BAR); + } + $config = $container->get('config'); + + if ( + ! array_key_exists('application', $config) + || ! is_array($config['application']) + || empty($config['application']) + ) { + throw new Exception(DebugBarFactory::MESSAGE_MISSING_CONFIG_APPLICATION); + } + + if ( + ! array_key_exists('url', $config['application']) + || ! is_string($config['application']['url']) + || empty($config['application']['url']) + ) { + throw new Exception(DebugBarFactory::MESSAGE_MISSING_CONFIG_APPLICATION_URL); + } + return new DebugBarExtension( - $container->get(DebugBar::class), - $container->get('config') + $container->get(DebugBarInterface::class), + $config['application']['url'] ); } } diff --git a/src/Factory/DebugBarFactory.php b/src/Factory/DebugBarFactory.php index 0e11699..b06fa21 100644 --- a/src/Factory/DebugBarFactory.php +++ b/src/Factory/DebugBarFactory.php @@ -1,29 +1,70 @@ has(EntityManager::class)) { + throw new Exception(self::MESSAGE_MISSING_ENTITY_MANAGER); + } + + if (! $container->has('config')) { + throw new Exception(self::MESSAGE_MISSING_CONFIG); + } + $config = $container->get('config'); + + if (! array_key_exists('enabled', $config) || ! is_bool($config['enabled'])) { + throw new Exception(self::MESSAGE_MISSING_CONFIG_ENABLED); + } + + if (! array_key_exists('ipv4Whitelist', $config) || ! is_array($config['ipv4Whitelist'])) { + throw new Exception(self::MESSAGE_MISSING_CONFIG_IPV4_WHITELIST); + } + + if (! array_key_exists('ipv6Whitelist', $config) || ! is_array($config['ipv6Whitelist'])) { + throw new Exception(self::MESSAGE_MISSING_CONFIG_IPV6_WHITELIST); + } + + if (! array_key_exists('javascript_renderer', $config) || ! is_array($config['javascript_renderer'])) { + throw new Exception(self::MESSAGE_MISSING_CONFIG_JAVASCRIPT_RENDERER); + } + + /** @var EntityManager $em */ + $em = $container->get(EntityManager::class); return new DebugBar( - $container->get(EntityManager::class), + $em->getConnection()->getConfiguration(), $container->get('config') ?? [] ); } diff --git a/src/Factory/DebugBarMiddlewareFactory.php b/src/Factory/DebugBarMiddlewareFactory.php index e249a8e..07bbf59 100644 --- a/src/Factory/DebugBarMiddlewareFactory.php +++ b/src/Factory/DebugBarMiddlewareFactory.php @@ -1,12 +1,13 @@ has(DebugBarInterface::class)) { + throw new Exception(DebugBarFactory::MESSAGE_MISSING_DEBUG_BAR); + } + + if (! $container->has(ResponseInterface::class)) { + throw new Exception(self::MESSAGE_MISSING_RESPONSE_INTERFACE); + } + return new DebugBarMiddleware( - $container->get(DebugBar::class), + $container->get(DebugBarInterface::class), $container->get(ResponseInterface::class), $container->has(ErrorResponseGenerator::class) ? $container->get(ErrorResponseGenerator::class) diff --git a/src/Middleware/DebugBarMiddleware.php b/src/Middleware/DebugBarMiddleware.php index 7999c1e..16df017 100644 --- a/src/Middleware/DebugBarMiddleware.php +++ b/src/Middleware/DebugBarMiddleware.php @@ -1,10 +1,10 @@ debugBar = $debugBar; - $this->responseFactory = static fn(): ResponseInterface => $responseFactory(); + public function __construct( + DebugBarInterface $debugBar, + callable $responseFactory, + ?callable $responseGenerator = null + ) { + $this->debugBar = $debugBar; + $this->responseFactory = static fn(): ResponseInterface => $responseFactory(); $this->responseGenerator = $responseGenerator ?: new ErrorResponseGenerator(); } - /** - * @param ServerRequestInterface $request - * @param RequestHandlerInterface $handler - * @return ResponseInterface - */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { if ($this->debugBar->shouldEnable($request->getServerParams()['REMOTE_ADDR'])) { @@ -63,16 +57,10 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface } } - /** - * Creates and returns a callable error handler that raises exceptions. - * - * Only raises exceptions for errors that are within the error_reporting mask. - */ - private function createErrorHandler() : callable + private function createErrorHandler(): callable { - return function (int $errno, string $errstr, string $errfile, int $errline) : void { + return function (int $errno, string $errstr, string $errfile, int $errline): void { if (! (error_reporting() & $errno)) { - // error_reporting does not include this error return; } @@ -80,13 +68,6 @@ private function createErrorHandler() : callable }; } - /** - * Handles all throwables, generating and returning a response. - * - * Passes the error, request, and response prototype to createErrorResponse(), - * triggers all listeners with the same arguments (but using the response - * returned from createErrorResponse()), and then returns the response. - */ private function handleThrowable(Throwable $e, ServerRequestInterface $request): ResponseInterface { $generator = $this->responseGenerator; diff --git a/src/Middleware/DebugBarMiddlewareInterface.php b/src/Middleware/DebugBarMiddlewareInterface.php index 3f19cca..5da2593 100644 --- a/src/Middleware/DebugBarMiddlewareInterface.php +++ b/src/Middleware/DebugBarMiddlewareInterface.php @@ -1,9 +1,14 @@ true, + 'ipv4Whitelist' => [], + 'ipv6Whitelist' => [], + 'javascript_renderer' => [], + 'application' => [ + 'url' => 'https://example.com', + ], + ]; +} diff --git a/test/ConfigProviderTest.php b/test/ConfigProviderTest.php new file mode 100644 index 0000000..338701c --- /dev/null +++ b/test/ConfigProviderTest.php @@ -0,0 +1,55 @@ +config = (new ConfigProvider())(); + } + + public function testHasDependencies(): void + { + $this->assertArrayHasKey('dependencies', $this->config); + } + + public function testDependenciesHasFactories(): void + { + $this->assertArrayHasKey('factories', $this->config['dependencies']); + + $factories = $this->config['dependencies']['factories']; + $this->assertArrayHasKey(DebugBar::class, $factories); + $this->assertSame(DebugBarFactory::class, $factories[DebugBar::class]); + $this->assertArrayHasKey(DebugBarExtension::class, $factories); + $this->assertSame(DebugBarExtensionFactory::class, $factories[DebugBarExtension::class]); + $this->assertArrayHasKey(DebugBarMiddleware::class, $factories); + $this->assertSame(DebugBarMiddlewareFactory::class, $factories[DebugBarMiddleware::class]); + } + + public function testDependenciesHasAliases(): void + { + $this->assertArrayHasKey('aliases', $this->config['dependencies']); + + $aliases = $this->config['dependencies']['aliases']; + $this->assertArrayHasKey(DebugBarInterface::class, $aliases); + $this->assertSame(DebugBar::class, $aliases[DebugBarInterface::class]); + $this->assertArrayHasKey(DebugBarMiddlewareInterface::class, $aliases); + $this->assertSame(DebugBarMiddleware::class, $aliases[DebugBarMiddlewareInterface::class]); + } +} diff --git a/test/DummyResponse.php b/test/DummyResponse.php new file mode 100644 index 0000000..6fea2c4 --- /dev/null +++ b/test/DummyResponse.php @@ -0,0 +1,73 @@ +assertNull(null); + } + + /** + * @throws Exception + */ + public function testGetFunctions(): void + { + $dotDebugBar = $this->createMock(DebugBar::class); + $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $functions = $extension->getFunctions(); + $this->assertIsArray($functions); + $this->assertCount(3, $functions); + $this->assertInstanceOf(TwigFunction::class, $functions[0]); + $this->assertInstanceOf(TwigFunction::class, $functions[1]); + $this->assertInstanceOf(TwigFunction::class, $functions[2]); + $this->assertSame('debugBarEnabled', $functions[0]->getName()); + $this->assertSame('debugBarCss', $functions[1]->getName()); + $this->assertSame('debugBarJs', $functions[2]->getName()); + } + + /** + * @throws Exception + * @throws DebugBarException + */ + public function testRenderDebugBarEnabledReturnsTrueWhenEnabled(): void + { + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, []); + $dotDebugBar->enable(); + + $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $this->assertTrue($extension->renderDebugBarEnabled()); + } + + /** + * @throws Exception + * @throws DebugBarException + */ + public function testRenderDebugBarEnabledReturnsFalseWhenDisabled(): void + { + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, []); + $dotDebugBar->disable(); + + $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $this->assertFalse($extension->renderDebugBarEnabled()); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillNotRenderDebugBarCssWhenDisabled(): void + { + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, []); + $dotDebugBar->disable(); + + $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $this->assertNull($extension->renderDebugBarCss()); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillRenderDebugBarCssWhenEnabled(): void + { + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, []); + $dotDebugBar->enable(); + + $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $html = $extension->renderDebugBarCss(); + $this->assertStringContainsString('dotkernel.css', $html); + $this->assertStringContainsString('debugbar.css', $html); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillNotRenderDebugBarJsWhenDisabled(): void + { + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, []); + $dotDebugBar->disable(); + + $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $this->assertNull($extension->renderDebugBarJs()); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillRenderDebugBarJsWhenEnabled(): void + { + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, []); + $dotDebugBar->enable(); + + $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $html = $extension->renderDebugBarJs(); + $this->assertStringContainsString('var phpdebugbar = new PhpDebugBar.DebugBar();', $html); + $this->assertStringContainsString('debugbar.js', $html); + } +} diff --git a/test/Factory/DebugBarExtensionFactoryTest.php b/test/Factory/DebugBarExtensionFactoryTest.php new file mode 100644 index 0000000..917490f --- /dev/null +++ b/test/Factory/DebugBarExtensionFactoryTest.php @@ -0,0 +1,81 @@ +createMock(ContainerInterface::class); + + $container->expects($this->once()) + ->method('has') + ->with('config') + ->willReturn(false); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_CONFIG); + (new DebugBarExtensionFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function testWillNotCreateExtensionWithoutDebugBar(): void + { + $container = $this->createMock(ContainerInterface::class); + + $container->method('has')->willReturnMap([ + ['config', true], + [DebugBarInterface::class, false], + ]); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_DEBUG_BAR); + (new DebugBarExtensionFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function testWillCreateExtension(): void + { + $container = $this->createMock(ContainerInterface::class); + $debugBar = $this->createMock(DebugBarInterface::class); + + $container->method('has')->willReturnMap([ + ['config', true], + [DebugBarInterface::class, true], + ]); + + $container->method('get')->willReturnMap([ + ['config', $this->config], + [DebugBarInterface::class, $debugBar], + ]); + + $extension = (new DebugBarExtensionFactory())($container); + $this->assertInstanceOf(DebugBarExtension::class, $extension); + } +} diff --git a/test/Factory/DebugBarFactoryTest.php b/test/Factory/DebugBarFactoryTest.php new file mode 100644 index 0000000..72039b1 --- /dev/null +++ b/test/Factory/DebugBarFactoryTest.php @@ -0,0 +1,210 @@ +createMock(ContainerInterface::class); + + $container->expects($this->once()) + ->method('has') + ->with(EntityManager::class) + ->willReturn(false); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_ENTITY_MANAGER); + (new DebugBarFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws DebugBarException + */ + public function testWillNotCreateServiceWithoutConfig(): void + { + $container = $this->createMock(ContainerInterface::class); + + $container->method('has')->willReturnMap([ + [EntityManager::class, true], + ['config', false], + ]); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_CONFIG); + (new DebugBarFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws DebugBarException + */ + public function testWillNotCreateServiceWithoutMissingConfigEnabled(): void + { + $container = $this->createMock(ContainerInterface::class); + + $container->method('has')->willReturnMap([ + [EntityManager::class, true], + ['config', true], + ]); + + $container->method('get')->willReturnMap([ + [EntityManager::class, true], + [ + 'config', + [ + 'test', + ], + ], + ]); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_CONFIG_ENABLED); + (new DebugBarFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws DebugBarException + */ + public function testWillNotCreateServiceWithoutMissingConfigIPv4Whitelist(): void + { + $container = $this->createMock(ContainerInterface::class); + + $container->method('has')->willReturnMap([ + [EntityManager::class, true], + ['config', true], + ]); + + $container->method('get')->willReturnMap([ + [EntityManager::class, true], + [ + 'config', + [ + 'enabled' => true, + ], + ], + ]); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_CONFIG_IPV4_WHITELIST); + (new DebugBarFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws DebugBarException + */ + public function testWillNotCreateServiceWithoutMissingConfigIPv6Whitelist(): void + { + $container = $this->createMock(ContainerInterface::class); + + $container->method('has')->willReturnMap([ + [EntityManager::class, true], + ['config', true], + ]); + + $container->method('get')->willReturnMap([ + [EntityManager::class, true], + [ + 'config', + [ + 'enabled' => true, + 'ipv4Whitelist' => [], + ], + ], + ]); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_CONFIG_IPV6_WHITELIST); + (new DebugBarFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws DebugBarException + */ + public function testWillNotCreateServiceWithoutMissingConfigJavaScriptRenderer(): void + { + $container = $this->createMock(ContainerInterface::class); + + $container->method('has')->willReturnMap([ + [EntityManager::class, true], + ['config', true], + ]); + + $container->method('get')->willReturnMap([ + [EntityManager::class, true], + [ + 'config', + [ + 'enabled' => true, + 'ipv4Whitelist' => [], + 'ipv6Whitelist' => [], + ], + ], + ]); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_CONFIG_JAVASCRIPT_RENDERER); + (new DebugBarFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws DebugBarException + */ + public function testWillCreateService(): void + { + $configuration = $this->createMock(Configuration::class); + $connection = $this->createMock(Connection::class); + $container = $this->createMock(ContainerInterface::class); + $em = $this->createMock(EntityManager::class); + + $container->method('has')->willReturnMap([ + [EntityManager::class, true], + ['config', true], + ]); + + $container->method('get')->willReturnMap([ + [EntityManager::class, $em], + ['config', $this->config], + ]); + + $em->expects($this->once())->method('getConnection')->willReturn($connection); + $connection->expects($this->once())->method('getConfiguration')->willReturn($configuration); + + $service = (new DebugBarFactory())($container); + $this->assertInstanceOf(DebugBarInterface::class, $service); + } +} diff --git a/test/Factory/DebugBarMiddlewareFactoryTest.php b/test/Factory/DebugBarMiddlewareFactoryTest.php new file mode 100644 index 0000000..df7ee15 --- /dev/null +++ b/test/Factory/DebugBarMiddlewareFactoryTest.php @@ -0,0 +1,83 @@ +createMock(ContainerInterface::class); + + $container->expects($this->once()) + ->method('has') + ->with(DebugBarInterface::class) + ->willReturn(false); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_DEBUG_BAR); + (new DebugBarMiddlewareFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function testWillNotCreateServiceWithoutResponseInterface(): void + { + $container = $this->createMock(ContainerInterface::class); + + $container->method('has')->willReturnMap([ + [DebugBarInterface::class, true], + [ResponseInterface::class, false], + ]); + + $this->expectExceptionMessage(DebugBarMiddlewareFactory::MESSAGE_MISSING_RESPONSE_INTERFACE); + (new DebugBarMiddlewareFactory())($container); + } + + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function testWillCreateMiddleware(): void + { + $container = $this->createMock(ContainerInterface::class); + $debugBar = $this->createMock(DebugBarInterface::class); + + $container->method('has')->willReturnMap([ + [DebugBarInterface::class, true], + [ResponseInterface::class, true], + ]); + + $container->method('get')->willReturnMap([ + [DebugBarInterface::class, $debugBar], + [ResponseInterface::class, new DummyResponse()], + ]); + + $middleware = (new DebugBarMiddlewareFactory())($container); + $this->assertInstanceOf(DebugBarMiddlewareInterface::class, $middleware); + } +} diff --git a/test/Middleware/DebugBarMiddlewareTest.php b/test/Middleware/DebugBarMiddlewareTest.php new file mode 100644 index 0000000..9251879 --- /dev/null +++ b/test/Middleware/DebugBarMiddlewareTest.php @@ -0,0 +1,83 @@ +createMock(DebugBarInterface::class); + $middleware = new DebugBarMiddleware($debugBar, new DummyResponse()); + $this->assertInstanceOf(DebugBarMiddlewareInterface::class, $middleware); + } + + /** + * @throws Exception + */ + public function testCanProcess(): void + { + $debugBar = $this->createMock(DebugBarInterface::class); + $request = $this->createMock(ServerRequestInterface::class); + $handler = $this->createMock(RequestHandlerInterface::class); + + $request->expects($this->once())->method('getServerParams')->willReturn([ + 'REMOTE_ADDR' => '127.0.0.1', + ]); + + $debugBar->expects($this->once())->method('shouldEnable')->withAnyParameters()->willReturn(true); + + $middleware = new DebugBarMiddleware($debugBar, new DummyResponse()); + $response = $middleware->process($request, $handler); + $this->assertInstanceOf(ResponseInterface::class, $response); + } + + /** + * @throws Exception + * @throws ReflectionException + */ + public function testCreateErrorHandler(): void + { + $debugBar = $this->createMock(DebugBarInterface::class); + $middleware = new DebugBarMiddleware($debugBar, new DummyResponse()); + $reflection = new ReflectionMethod(DebugBarMiddleware::class, 'createErrorHandler'); + + $callable = $reflection->invoke($middleware); + $this->assertIsCallable($callable); + } + + /** + * @throws Exception + * @throws ReflectionException + */ + public function testHandleThrowable(): void + { + $debugBar = $this->createMock(DebugBarInterface::class); + $request = $this->createMock(ServerRequestInterface::class); + $response = $this->createMock(DummyResponse::class); + + $response->expects($this->once())->method('__invoke')->willReturn($response); + + $middleware = new DebugBarMiddleware($debugBar, $response); + $reflection = new ReflectionMethod(DebugBarMiddleware::class, 'handleThrowable'); + + $response = $reflection->invoke($middleware, new \Exception('test'), $request); + $this->assertInstanceOf(ResponseInterface::class, $response); + } +} From 21e7dc1413acfdd603d8385dda1b9859afc25726 Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Fri, 7 Jul 2023 14:47:11 +0300 Subject: [PATCH 02/10] Added missing github action files. Signed-off-by: alexmerlin --- .github/workflows/cs-tests.yml | 46 ++++++++++++++++++++++++++ .github/workflows/static-analysis.yml | 46 ++++++++++++++++++++++++++ .github/workflows/unit-tests.yml | 47 +++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 .github/workflows/cs-tests.yml create mode 100644 .github/workflows/static-analysis.yml create mode 100644 .github/workflows/unit-tests.yml diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml new file mode 100644 index 0000000..3da9965 --- /dev/null +++ b/.github/workflows/cs-tests.yml @@ -0,0 +1,46 @@ +on: + - push + +name: Run phpcs checks + +jobs: + mutation: + name: PHP ${{ matrix.php }}-${{ matrix.os }} + + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: + - ubuntu-latest + + php: + - "8.1" + - "8.2" + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + tools: composer:v2, cs2pr + coverage: none + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php }}-composer- + - name: Install dependencies with composer + run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + + - name: Run phpcs checks + run: vendor/bin/phpcs diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 0000000..74550fc --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -0,0 +1,46 @@ +on: + - push + +name: Run static analysis + +jobs: + mutation: + name: PHP ${{ matrix.php }}-${{ matrix.os }} + + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: + - ubuntu-latest + + php: + - "8.1" + - "8.2" + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + tools: composer:v2, cs2pr + coverage: none + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php }}-composer- + - name: Install dependencies with composer + run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + + - name: Run static analysis + run: vendor/bin/psalm --no-cache --output-format=github --show-info=false --threads=4 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000..d2ab8e7 --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,47 @@ +on: + - push + +name: Run PHPUnit tests + +jobs: + mutation: + name: PHP ${{ matrix.php }}-${{ matrix.os }} + + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: + - ubuntu-latest + + php: + - "8.1" + - "8.2" + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + tools: composer:v2, cs2pr + coverage: none + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php }}-composer- + + - name: Install dependencies with composer + run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + + - name: Run PHPUnit tests + run: vendor/bin/phpunit --colors=always From f90bb1be9b1992b916ad91493210fd5ee91ddeb1 Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Fri, 7 Jul 2023 14:50:24 +0300 Subject: [PATCH 03/10] Restrict github actions to PHP 8.1 only. Signed-off-by: alexmerlin --- .github/workflows/cs-tests.yml | 1 - .github/workflows/static-analysis.yml | 1 - .github/workflows/unit-tests.yml | 1 - 3 files changed, 3 deletions(-) diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml index 3da9965..02d6d5e 100644 --- a/.github/workflows/cs-tests.yml +++ b/.github/workflows/cs-tests.yml @@ -16,7 +16,6 @@ jobs: php: - "8.1" - - "8.2" steps: - name: Checkout diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 74550fc..e0e2cdb 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -16,7 +16,6 @@ jobs: php: - "8.1" - - "8.2" steps: - name: Checkout diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index d2ab8e7..317b4d0 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -16,7 +16,6 @@ jobs: php: - "8.1" - - "8.2" steps: - name: Checkout From aacef8f2a61e49691053c0416b65c75cebe90fed Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Fri, 7 Jul 2023 17:18:11 +0300 Subject: [PATCH 04/10] Added DebugBar test Signed-off-by: alexmerlin --- psalm-baseline.xml | 7 + src/DebugBar.php | 26 ++- src/DebugBarInterface.php | 9 +- src/Factory/DebugBarExtensionFactory.php | 16 +- src/Factory/DebugBarFactory.php | 12 +- test/CommonTrait.php | 16 +- test/DebugBarTest.php | 196 ++++++++++++++++++ test/Extension/DebugBarExtensionTest.php | 14 +- test/Factory/DebugBarExtensionFactoryTest.php | 30 ++- test/Factory/DebugBarFactoryTest.php | 23 +- 10 files changed, 311 insertions(+), 38 deletions(-) create mode 100644 test/DebugBarTest.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 1efa45c..53d3486 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,12 @@ + + + getJavascriptRenderer + getJavascriptRenderer + getJavascriptRenderer + + ErrorResponseGenerator diff --git a/src/DebugBar.php b/src/DebugBar.php index ec5b7d5..83992a1 100644 --- a/src/DebugBar.php +++ b/src/DebugBar.php @@ -58,7 +58,7 @@ public function __construct(Configuration $configuration, array $config) $this->addCollector($this->timeDataCollector = new TimeDataCollector()); $this->addCollector($this->exceptionsCollector = new ExceptionsCollector()); - $this->config = $config[self::class] ?? []; + $this->config = $config; $this->getJavascriptRenderer()->addAssets( [ @@ -79,19 +79,27 @@ public function __construct(Configuration $configuration, array $config) } } - public function shouldEnable(string $ipAddress): bool + public function getExceptionsCollector(): ExceptionsCollector { - /** - * If config file is missing: DebugBar is disabled - */ - if (empty($this->config)) { - return false; - } + return $this->exceptionsCollector; + } + + public function getMessagesCollector(): MessagesCollector + { + return $this->messagesCollector; + } + public function getTimeDataCollector(): TimeDataCollector + { + return $this->timeDataCollector; + } + + public function shouldEnable(string $ipAddress): bool + { /** * If config.enabled is missing/empty/false: DebugBar is disabled */ - if (empty($this->config['enabled'])) { + if (false === $this->config['enabled']) { return false; } diff --git a/src/DebugBarInterface.php b/src/DebugBarInterface.php index 239f3d1..5d24b99 100644 --- a/src/DebugBarInterface.php +++ b/src/DebugBarInterface.php @@ -5,6 +5,9 @@ namespace Dot\DebugBar; use Closure; +use DebugBar\DataCollector\ExceptionsCollector; +use DebugBar\DataCollector\MessagesCollector; +use DebugBar\DataCollector\TimeDataCollector; use DebugBar\DebugBarException; use Throwable; @@ -18,7 +21,11 @@ public function disable(): self; public function enable(): self; - public function getJavascriptRenderer(?string $baseUrl = null, ?string $basePath = null); + public function getExceptionsCollector(): ExceptionsCollector; + + public function getMessagesCollector(): MessagesCollector; + + public function getTimeDataCollector(): TimeDataCollector; public function isEnabled(): bool; diff --git a/src/Factory/DebugBarExtensionFactory.php b/src/Factory/DebugBarExtensionFactory.php index 823352d..b30b117 100644 --- a/src/Factory/DebugBarExtensionFactory.php +++ b/src/Factory/DebugBarExtensionFactory.php @@ -4,6 +4,7 @@ namespace Dot\DebugBar\Factory; +use Dot\DebugBar\DebugBar; use Dot\DebugBar\DebugBarInterface; use Dot\DebugBar\Extension\DebugBarExtension; use Exception; @@ -24,14 +25,23 @@ class DebugBarExtensionFactory */ public function __invoke(ContainerInterface $container): DebugBarExtension { + if (! $container->has(DebugBarInterface::class)) { + throw new Exception(DebugBarFactory::MESSAGE_MISSING_DEBUG_BAR); + } + if (! $container->has('config')) { throw new Exception(DebugBarFactory::MESSAGE_MISSING_CONFIG); } + $config = $container->get('config'); - if (! $container->has(DebugBarInterface::class)) { - throw new Exception(DebugBarFactory::MESSAGE_MISSING_DEBUG_BAR); + if ( + ! array_key_exists(DebugBar::class, $config) + || ! is_array($config[DebugBar::class]) + || empty($config[DebugBar::class]) + ) { + throw new Exception(DebugBarFactory::MESSAGE_MISSING_PACKAGE_CONFIG); } - $config = $container->get('config'); + $config = $config[DebugBar::class]; if ( ! array_key_exists('application', $config) diff --git a/src/Factory/DebugBarFactory.php b/src/Factory/DebugBarFactory.php index b06fa21..fa84e8d 100644 --- a/src/Factory/DebugBarFactory.php +++ b/src/Factory/DebugBarFactory.php @@ -18,6 +18,7 @@ class DebugBarFactory { + public const MESSAGE_MISSING_PACKAGE_CONFIG = 'Unable to find dot-debugbar config'; public const MESSAGE_MISSING_CONFIG = 'Unable to find config in the container'; public const MESSAGE_MISSING_CONFIG_APPLICATION = 'Missing/invalid config: application'; public const MESSAGE_MISSING_CONFIG_APPLICATION_URL = 'Missing/invalid config: application url'; @@ -45,6 +46,15 @@ public function __invoke(ContainerInterface $container): DebugBar } $config = $container->get('config'); + if ( + ! array_key_exists(DebugBar::class, $config) + || ! is_array($config[DebugBar::class]) + || empty($config[DebugBar::class]) + ) { + throw new Exception(self::MESSAGE_MISSING_PACKAGE_CONFIG); + } + $config = $config[DebugBar::class]; + if (! array_key_exists('enabled', $config) || ! is_bool($config['enabled'])) { throw new Exception(self::MESSAGE_MISSING_CONFIG_ENABLED); } @@ -65,7 +75,7 @@ public function __invoke(ContainerInterface $container): DebugBar $em = $container->get(EntityManager::class); return new DebugBar( $em->getConnection()->getConfiguration(), - $container->get('config') ?? [] + $config ); } } diff --git a/test/CommonTrait.php b/test/CommonTrait.php index 84bcb6d..285a6b5 100644 --- a/test/CommonTrait.php +++ b/test/CommonTrait.php @@ -4,15 +4,19 @@ namespace DotTest\DebugBar; +use Dot\DebugBar\DebugBar; + trait CommonTrait { protected array $config = [ - 'enabled' => true, - 'ipv4Whitelist' => [], - 'ipv6Whitelist' => [], - 'javascript_renderer' => [], - 'application' => [ - 'url' => 'https://example.com', + DebugBar::class => [ + 'enabled' => true, + 'ipv4Whitelist' => [], + 'ipv6Whitelist' => [], + 'javascript_renderer' => [], + 'application' => [ + 'url' => 'https://example.com', + ], ], ]; } diff --git a/test/DebugBarTest.php b/test/DebugBarTest.php new file mode 100644 index 0000000..82d6f4c --- /dev/null +++ b/test/DebugBarTest.php @@ -0,0 +1,196 @@ +createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $this->config); + $this->assertInstanceOf(DebugBar::class, $dotDebugBar); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillNotEnableIfConfigDisabled(): void + { + $config = $this->config[DebugBar::class]; + $config['enabled'] = false; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertFalse($dotDebugBar->shouldEnable('')); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillNotEnableIfConfigEnabledButIpAddressIsInvalid(): void + { + $config = $this->config[DebugBar::class]; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertFalse($dotDebugBar->shouldEnable('test')); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillNotEnableIfConfigEnabledAndValidIpv4AddressNotWhitelisted(): void + { + $config = $this->config[DebugBar::class]; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertFalse($dotDebugBar->shouldEnable('127.0.0.1')); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillNotEnableIfConfigEnabledAndValidIpv6AddressNotWhitelisted(): void + { + $config = $this->config[DebugBar::class]; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertFalse( + $dotDebugBar->shouldEnable('::1') + ); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillEnableIfConfigEnabledAndValidWhitelistedIpv4Address(): void + { + $config = $this->config[DebugBar::class]; + $config['ipv4Whitelist'][] = '127.0.0.1'; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertTrue($dotDebugBar->shouldEnable('127.0.0.1')); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillEnableIfConfigEnabledAndValidWhitelistedIpv6Address(): void + { + $config = $this->config[DebugBar::class]; + $config['ipv6Whitelist'][] = '::1'; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertTrue($dotDebugBar->shouldEnable('::1')); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillEnableIfConfigEnabledAndAllowAnyValidIpv4Address(): void + { + $config = $this->config[DebugBar::class]; + $config['ipv4Whitelist'][] = '*'; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertTrue($dotDebugBar->shouldEnable('127.0.0.1')); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillEnableIfConfigEnabledAndAllowAnyValidIpv6Address(): void + { + $config = $this->config[DebugBar::class]; + $config['ipv6Whitelist'][] = '*'; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertTrue($dotDebugBar->shouldEnable('::1')); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillToggle(): void + { + $config = $this->config[DebugBar::class]; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertFalse($dotDebugBar->isEnabled()); + $dotDebugBar->enable(); + $this->assertInstanceOf(DebugBar::class, $dotDebugBar); + $this->assertTrue($dotDebugBar->isEnabled()); + $dotDebugBar->disable(); + $this->assertInstanceOf(DebugBar::class, $dotDebugBar); + $this->assertFalse($dotDebugBar->isEnabled()); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillAddMessage(): void + { + $config = $this->config[DebugBar::class]; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertCount(0, $dotDebugBar->getMessagesCollector()->getMessages()); + $dotDebugBar->addMessage('test'); + $this->assertInstanceOf(DebugBar::class, $dotDebugBar); + $this->assertCount(1, $dotDebugBar->getMessagesCollector()->getMessages()); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillStartStopMeasureTimer(): void + { + $config = $this->config[DebugBar::class]; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertFalse($dotDebugBar->getTimeDataCollector()->hasStartedMeasure('test')); + $dotDebugBar->startTimer('test'); + $this->assertInstanceOf(DebugBar::class, $dotDebugBar); + $this->assertTrue($dotDebugBar->getTimeDataCollector()->hasStartedMeasure('test')); + $dotDebugBar->stopTimer('test'); + $this->assertInstanceOf(DebugBar::class, $dotDebugBar); + $this->assertFalse($dotDebugBar->getTimeDataCollector()->hasStartedMeasure('test')); + } + + /** + * @throws DebugBarException + * @throws Exception + */ + public function testWillAddThrowable(): void + { + $config = $this->config[DebugBar::class]; + $configuration = $this->createMock(Configuration::class); + $dotDebugBar = new DebugBar($configuration, $config); + $this->assertCount(0, $dotDebugBar->getExceptionsCollector()->getExceptions()); + $dotDebugBar->addThrowable(new \Exception('test')); + $this->assertInstanceOf(DebugBar::class, $dotDebugBar); + $this->assertCount(1, $dotDebugBar->getExceptionsCollector()->getExceptions()); + } +} diff --git a/test/Extension/DebugBarExtensionTest.php b/test/Extension/DebugBarExtensionTest.php index 85609e2..8425440 100644 --- a/test/Extension/DebugBarExtensionTest.php +++ b/test/Extension/DebugBarExtensionTest.php @@ -28,7 +28,7 @@ public function testConstructor(): void public function testGetFunctions(): void { $dotDebugBar = $this->createMock(DebugBar::class); - $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $extension = new DebugBarExtension($dotDebugBar, $this->config[DebugBar::class]['application']['url']); $functions = $extension->getFunctions(); $this->assertIsArray($functions); $this->assertCount(3, $functions); @@ -50,7 +50,7 @@ public function testRenderDebugBarEnabledReturnsTrueWhenEnabled(): void $dotDebugBar = new DebugBar($configuration, []); $dotDebugBar->enable(); - $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $extension = new DebugBarExtension($dotDebugBar, $this->config[DebugBar::class]['application']['url']); $this->assertTrue($extension->renderDebugBarEnabled()); } @@ -64,7 +64,7 @@ public function testRenderDebugBarEnabledReturnsFalseWhenDisabled(): void $dotDebugBar = new DebugBar($configuration, []); $dotDebugBar->disable(); - $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $extension = new DebugBarExtension($dotDebugBar, $this->config[DebugBar::class]['application']['url']); $this->assertFalse($extension->renderDebugBarEnabled()); } @@ -78,7 +78,7 @@ public function testWillNotRenderDebugBarCssWhenDisabled(): void $dotDebugBar = new DebugBar($configuration, []); $dotDebugBar->disable(); - $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $extension = new DebugBarExtension($dotDebugBar, $this->config[DebugBar::class]['application']['url']); $this->assertNull($extension->renderDebugBarCss()); } @@ -92,7 +92,7 @@ public function testWillRenderDebugBarCssWhenEnabled(): void $dotDebugBar = new DebugBar($configuration, []); $dotDebugBar->enable(); - $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $extension = new DebugBarExtension($dotDebugBar, $this->config[DebugBar::class]['application']['url']); $html = $extension->renderDebugBarCss(); $this->assertStringContainsString('dotkernel.css', $html); $this->assertStringContainsString('debugbar.css', $html); @@ -108,7 +108,7 @@ public function testWillNotRenderDebugBarJsWhenDisabled(): void $dotDebugBar = new DebugBar($configuration, []); $dotDebugBar->disable(); - $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $extension = new DebugBarExtension($dotDebugBar, $this->config[DebugBar::class]['application']['url']); $this->assertNull($extension->renderDebugBarJs()); } @@ -122,7 +122,7 @@ public function testWillRenderDebugBarJsWhenEnabled(): void $dotDebugBar = new DebugBar($configuration, []); $dotDebugBar->enable(); - $extension = new DebugBarExtension($dotDebugBar, $this->config['application']['url']); + $extension = new DebugBarExtension($dotDebugBar, $this->config[DebugBar::class]['application']['url']); $html = $extension->renderDebugBarJs(); $this->assertStringContainsString('var phpdebugbar = new PhpDebugBar.DebugBar();', $html); $this->assertStringContainsString('debugbar.js', $html); diff --git a/test/Factory/DebugBarExtensionFactoryTest.php b/test/Factory/DebugBarExtensionFactoryTest.php index 917490f..ee975b2 100644 --- a/test/Factory/DebugBarExtensionFactoryTest.php +++ b/test/Factory/DebugBarExtensionFactoryTest.php @@ -28,15 +28,37 @@ public function testWillNotCreateExtensionWithoutConfig(): void { $container = $this->createMock(ContainerInterface::class); - $container->expects($this->once()) - ->method('has') - ->with('config') - ->willReturn(false); + $container->method('has')->willReturnMap([ + [DebugBarInterface::class, true], + ['config', false], + ]); $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_CONFIG); (new DebugBarExtensionFactory())($container); } + /** + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function testWillNotCreateExtensionWithoutPackageConfig(): void + { + $container = $this->createMock(ContainerInterface::class); + + $container->method('has')->willReturnMap([ + [DebugBarInterface::class, true], + ['config', true], + ]); + + $container->method('get')->willReturn([ + 'test', + ]); + + $this->expectExceptionMessage(DebugBarFactory::MESSAGE_MISSING_PACKAGE_CONFIG); + (new DebugBarExtensionFactory())($container); + } + /** * @throws Exception * @throws ContainerExceptionInterface diff --git a/test/Factory/DebugBarFactoryTest.php b/test/Factory/DebugBarFactoryTest.php index 72039b1..c486461 100644 --- a/test/Factory/DebugBarFactoryTest.php +++ b/test/Factory/DebugBarFactoryTest.php @@ -8,6 +8,7 @@ use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; use Doctrine\ORM\EntityManager; +use Dot\DebugBar\DebugBar; use Dot\DebugBar\DebugBarInterface; use Dot\DebugBar\Factory\DebugBarFactory; use DotTest\DebugBar\CommonTrait; @@ -79,7 +80,9 @@ public function testWillNotCreateServiceWithoutMissingConfigEnabled(): void [ 'config', [ - 'test', + DebugBar::class => [ + 'test', + ], ], ], ]); @@ -108,7 +111,9 @@ public function testWillNotCreateServiceWithoutMissingConfigIPv4Whitelist(): voi [ 'config', [ - 'enabled' => true, + DebugBar::class => [ + 'enabled' => true, + ], ], ], ]); @@ -137,8 +142,10 @@ public function testWillNotCreateServiceWithoutMissingConfigIPv6Whitelist(): voi [ 'config', [ - 'enabled' => true, - 'ipv4Whitelist' => [], + DebugBar::class => [ + 'enabled' => true, + 'ipv4Whitelist' => [], + ], ], ], ]); @@ -167,9 +174,11 @@ public function testWillNotCreateServiceWithoutMissingConfigJavaScriptRenderer() [ 'config', [ - 'enabled' => true, - 'ipv4Whitelist' => [], - 'ipv6Whitelist' => [], + DebugBar::class => [ + 'enabled' => true, + 'ipv4Whitelist' => [], + 'ipv6Whitelist' => [], + ], ], ], ]); From 7f2b1e70da8d5b38e145b6bfb60a41a5357e8b97 Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Wed, 12 Jul 2023 12:13:46 +0300 Subject: [PATCH 05/10] readded PHP8.2 to GA files Signed-off-by: alexmerlin --- .github/workflows/cs-tests.yml | 1 + .github/workflows/static-analysis.yml | 1 + .github/workflows/unit-tests.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml index 02d6d5e..3da9965 100644 --- a/.github/workflows/cs-tests.yml +++ b/.github/workflows/cs-tests.yml @@ -16,6 +16,7 @@ jobs: php: - "8.1" + - "8.2" steps: - name: Checkout diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index e0e2cdb..74550fc 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -16,6 +16,7 @@ jobs: php: - "8.1" + - "8.2" steps: - name: Checkout diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 317b4d0..d2ab8e7 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -16,6 +16,7 @@ jobs: php: - "8.1" + - "8.2" steps: - name: Checkout From a71865078b6105a4020f6289a9f65f91514af3e8 Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Wed, 12 Jul 2023 12:50:41 +0300 Subject: [PATCH 06/10] update Signed-off-by: alexmerlin --- test/DummyResponse.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/DummyResponse.php b/test/DummyResponse.php index 6fea2c4..4c2e8ac 100644 --- a/test/DummyResponse.php +++ b/test/DummyResponse.php @@ -8,6 +8,8 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; +use function fopen; + class DummyResponse implements ResponseInterface { public function __invoke(): ResponseInterface @@ -53,6 +55,9 @@ public function withoutHeader(string $name): MessageInterface public function getBody(): StreamInterface { + /** @var StreamInterface $stream */ + $stream = fopen('php://temp', 'r'); + return $stream; } public function withBody(StreamInterface $body): MessageInterface From a26d4dadb75b96b9a7a08f30d47da6da5d114cdd Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Wed, 12 Jul 2023 13:04:16 +0300 Subject: [PATCH 07/10] update Signed-off-by: alexmerlin --- test/DummyResponse.php | 5 ----- test/Middleware/DebugBarMiddlewareTest.php | 19 ------------------- 2 files changed, 24 deletions(-) diff --git a/test/DummyResponse.php b/test/DummyResponse.php index 4c2e8ac..6fea2c4 100644 --- a/test/DummyResponse.php +++ b/test/DummyResponse.php @@ -8,8 +8,6 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; -use function fopen; - class DummyResponse implements ResponseInterface { public function __invoke(): ResponseInterface @@ -55,9 +53,6 @@ public function withoutHeader(string $name): MessageInterface public function getBody(): StreamInterface { - /** @var StreamInterface $stream */ - $stream = fopen('php://temp', 'r'); - return $stream; } public function withBody(StreamInterface $body): MessageInterface diff --git a/test/Middleware/DebugBarMiddlewareTest.php b/test/Middleware/DebugBarMiddlewareTest.php index 9251879..a895b68 100644 --- a/test/Middleware/DebugBarMiddlewareTest.php +++ b/test/Middleware/DebugBarMiddlewareTest.php @@ -61,23 +61,4 @@ public function testCreateErrorHandler(): void $callable = $reflection->invoke($middleware); $this->assertIsCallable($callable); } - - /** - * @throws Exception - * @throws ReflectionException - */ - public function testHandleThrowable(): void - { - $debugBar = $this->createMock(DebugBarInterface::class); - $request = $this->createMock(ServerRequestInterface::class); - $response = $this->createMock(DummyResponse::class); - - $response->expects($this->once())->method('__invoke')->willReturn($response); - - $middleware = new DebugBarMiddleware($debugBar, $response); - $reflection = new ReflectionMethod(DebugBarMiddleware::class, 'handleThrowable'); - - $response = $reflection->invoke($middleware, new \Exception('test'), $request); - $this->assertInstanceOf(ResponseInterface::class, $response); - } } From 468a1ade83826187c318e66e167c82d5ce38b61d Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Wed, 12 Jul 2023 13:08:04 +0300 Subject: [PATCH 08/10] update Signed-off-by: alexmerlin --- .github/workflows/cs-tests.yml | 1 - .github/workflows/static-analysis.yml | 1 - .github/workflows/unit-tests.yml | 1 - test/Middleware/DebugBarMiddlewareTest.php | 19 +++++++++++++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml index 3da9965..02d6d5e 100644 --- a/.github/workflows/cs-tests.yml +++ b/.github/workflows/cs-tests.yml @@ -16,7 +16,6 @@ jobs: php: - "8.1" - - "8.2" steps: - name: Checkout diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 74550fc..e0e2cdb 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -16,7 +16,6 @@ jobs: php: - "8.1" - - "8.2" steps: - name: Checkout diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index d2ab8e7..317b4d0 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -16,7 +16,6 @@ jobs: php: - "8.1" - - "8.2" steps: - name: Checkout diff --git a/test/Middleware/DebugBarMiddlewareTest.php b/test/Middleware/DebugBarMiddlewareTest.php index a895b68..9251879 100644 --- a/test/Middleware/DebugBarMiddlewareTest.php +++ b/test/Middleware/DebugBarMiddlewareTest.php @@ -61,4 +61,23 @@ public function testCreateErrorHandler(): void $callable = $reflection->invoke($middleware); $this->assertIsCallable($callable); } + + /** + * @throws Exception + * @throws ReflectionException + */ + public function testHandleThrowable(): void + { + $debugBar = $this->createMock(DebugBarInterface::class); + $request = $this->createMock(ServerRequestInterface::class); + $response = $this->createMock(DummyResponse::class); + + $response->expects($this->once())->method('__invoke')->willReturn($response); + + $middleware = new DebugBarMiddleware($debugBar, $response); + $reflection = new ReflectionMethod(DebugBarMiddleware::class, 'handleThrowable'); + + $response = $reflection->invoke($middleware, new \Exception('test'), $request); + $this->assertInstanceOf(ResponseInterface::class, $response); + } } From 3ceb505e93a2726cb1daf128eff6a32d8d8ecc57 Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Wed, 12 Jul 2023 13:10:35 +0300 Subject: [PATCH 09/10] update Signed-off-by: alexmerlin --- test/Middleware/DebugBarMiddlewareTest.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/test/Middleware/DebugBarMiddlewareTest.php b/test/Middleware/DebugBarMiddlewareTest.php index 9251879..a895b68 100644 --- a/test/Middleware/DebugBarMiddlewareTest.php +++ b/test/Middleware/DebugBarMiddlewareTest.php @@ -61,23 +61,4 @@ public function testCreateErrorHandler(): void $callable = $reflection->invoke($middleware); $this->assertIsCallable($callable); } - - /** - * @throws Exception - * @throws ReflectionException - */ - public function testHandleThrowable(): void - { - $debugBar = $this->createMock(DebugBarInterface::class); - $request = $this->createMock(ServerRequestInterface::class); - $response = $this->createMock(DummyResponse::class); - - $response->expects($this->once())->method('__invoke')->willReturn($response); - - $middleware = new DebugBarMiddleware($debugBar, $response); - $reflection = new ReflectionMethod(DebugBarMiddleware::class, 'handleThrowable'); - - $response = $reflection->invoke($middleware, new \Exception('test'), $request); - $this->assertInstanceOf(ResponseInterface::class, $response); - } } From 925b0c9760d0989c0dbafc176ba979d08d3a50fe Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Wed, 12 Jul 2023 14:34:17 +0300 Subject: [PATCH 10/10] update Signed-off-by: alexmerlin --- .github/workflows/cs-tests.yml | 1 + .github/workflows/static-analysis.yml | 1 + .github/workflows/unit-tests.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml index 02d6d5e..3da9965 100644 --- a/.github/workflows/cs-tests.yml +++ b/.github/workflows/cs-tests.yml @@ -16,6 +16,7 @@ jobs: php: - "8.1" + - "8.2" steps: - name: Checkout diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index e0e2cdb..74550fc 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -16,6 +16,7 @@ jobs: php: - "8.1" + - "8.2" steps: - name: Checkout diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 317b4d0..d2ab8e7 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -16,6 +16,7 @@ jobs: php: - "8.1" + - "8.2" steps: - name: Checkout