From 224dca7e593767a749e8bdafcf98504670c0fa0a Mon Sep 17 00:00:00 2001 From: Luiz Marin <67489841+luizcmarin@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:43:24 -0300 Subject: [PATCH 1/9] Update file (#140) --- LICENSE.md | 8 ++++---- README.md | 33 ++++++++++++++------------------- composer.json | 2 +- docs/internals.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 24 deletions(-) create mode 100644 docs/internals.md diff --git a/LICENSE.md b/LICENSE.md index bc5674f..6a920d6 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,17 +1,17 @@ -Copyright © 2008 by Yii Software (https://www.yiiframework.com/) +Copyright © 2008 by Yii Software () All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Yii Software nor the names of its +* Neither the name of Yii Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/README.md b/README.md index 27deffb..dbf69b2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ -

Yii debug API

+

Yii Debug API


@@ -33,31 +33,26 @@ composer require yiisoft/yii-debug-api Routes will be registered automatically within Yii application router. You can check if everything is OK by going to `/debug` URL. -## Testing +## Documentation -### Unit testing +- [Internals](docs/internals.md) -The package is tested with [PHPUnit](https://phpunit.de/). To run tests: +## Support -```shell -./vendor/bin/phpunit -``` - -### Mutation testing - -The package tests are checked with [Infection](https://infection.github.io/) mutation framework. To run it: +If you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/63) is a good place for that. +You may also check out other [Yii Community Resources](https://www.yiiframework.com/community). -```shell -./vendor/bin/infection -``` +## Support the project -### Static analysis +[![Open Collective](https://img.shields.io/badge/Open%20Collective-sponsor-7eadf1?logo=open%20collective&logoColor=7eadf1&labelColor=555555)](https://opencollective.com/yiisoft) -The code is statically analyzed with [Psalm](https://psalm.dev/). To run static analysis: +## Follow updates -```shell -./vendor/bin/psalm -``` +[![Official website](https://img.shields.io/badge/Powered_by-Yii_Framework-green.svg?style=flat)](https://www.yiiframework.com/) +[![Twitter](https://img.shields.io/badge/twitter-follow-1DA1F2?logo=twitter&logoColor=1DA1F2&labelColor=555555?style=flat)](https://twitter.com/yiiframework) +[![Telegram](https://img.shields.io/badge/telegram-join-1DA1F2?style=flat&logo=telegram)](https://t.me/yii3en) +[![Facebook](https://img.shields.io/badge/facebook-join-1DA1F2?style=flat&logo=facebook&logoColor=ffffff)](https://www.facebook.com/groups/yiitalk) +[![Slack](https://img.shields.io/badge/slack-join-1DA1F2?style=flat&logo=slack)](https://yiiframework.com/go/slack) ## License diff --git a/composer.json b/composer.json index 8fba472..b83494e 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "issues": "https://github.com/yiisoft/yii-debug-api/issues?state=open", "forum": "https://www.yiiframework.com/forum/", "wiki": "https://www.yiiframework.com/wiki/", - "irc": "irc://irc.freenode.net/yii", + "irc": "ircs://irc.libera.chat:6697/yii", "chat": "https://t.me/yii3en", "source": "https://github.com/yiisoft/yii-debug-api" }, diff --git a/docs/internals.md b/docs/internals.md new file mode 100644 index 0000000..8dc4049 --- /dev/null +++ b/docs/internals.md @@ -0,0 +1,45 @@ +# Internals + +## Unit testing + +The package is tested with [PHPUnit](https://phpunit.de/). To run tests: + +```shell +./vendor/bin/phpunit +``` + +## Mutation testing + +The package tests are checked with [Infection](https://infection.github.io/) mutation framework with +[Infection Static Analysis Plugin](https://github.com/Roave/infection-static-analysis-plugin). To run it: + +```shell +./vendor/bin/roave-infection-static-analysis-plugin +``` + +## Static analysis + +The code is statically analyzed with [Psalm](https://psalm.dev/). To run static analysis: + +```shell +./vendor/bin/psalm +``` + +## Rector + +Use [Rector](https://github.com/rectorphp/rector) to make codebase follow some specific rules or +use either newest or any specific version of PHP: + +```shell +./vendor/bin/rector +``` + +## Composer require checker + +This package uses [composer-require-checker](https://github.com/maglnet/ComposerRequireChecker) to check if all dependencies are correctly defined in `composer.json`. + +To run the checker, execute the following command: + +```shell +./vendor/bin/composer-require-checker +``` From cbfcaf4155a009403a778bd9b6c6aed426c75c58 Mon Sep 17 00:00:00 2001 From: Luiz Marin <67489841+luizcmarin@users.noreply.github.com> Date: Wed, 15 May 2024 03:45:25 -0300 Subject: [PATCH 2/9] Fix docs (#141) Co-authored-by: Sergei Predvoditelev --- LICENSE.md | 6 +++--- README.md | 18 ++++++++---------- docs/internals.md | 9 ++++----- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 6a920d6..c48bcea 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -5,13 +5,13 @@ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -* Neither the name of Yii Software nor the names of its + * Neither the name of Yii Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/README.md b/README.md index dbf69b2..92dfe39 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ This extension provides an API for [Yii Debug](https://github.com/yiisoft/yii-de ## Installation -Add the package to your application: +The package could be installed with [Composer](https://getcomposer.org): ```shell composer require yiisoft/yii-debug-api @@ -37,11 +37,16 @@ You can check if everything is OK by going to `/debug` URL. - [Internals](docs/internals.md) -## Support - If you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/63) is a good place for that. You may also check out other [Yii Community Resources](https://www.yiiframework.com/community). +## License + +The Yii Debug API is free software. It is released under the terms of the BSD License. +Please see [`LICENSE`](./LICENSE.md) for more information. + +Maintained by [Yii Software](https://www.yiiframework.com/). + ## Support the project [![Open Collective](https://img.shields.io/badge/Open%20Collective-sponsor-7eadf1?logo=open%20collective&logoColor=7eadf1&labelColor=555555)](https://opencollective.com/yiisoft) @@ -53,10 +58,3 @@ You may also check out other [Yii Community Resources](https://www.yiiframework. [![Telegram](https://img.shields.io/badge/telegram-join-1DA1F2?style=flat&logo=telegram)](https://t.me/yii3en) [![Facebook](https://img.shields.io/badge/facebook-join-1DA1F2?style=flat&logo=facebook&logoColor=ffffff)](https://www.facebook.com/groups/yiitalk) [![Slack](https://img.shields.io/badge/slack-join-1DA1F2?style=flat&logo=slack)](https://yiiframework.com/go/slack) - -## License - -The Yii Debug API is free software. It is released under the terms of the BSD License. -Please see [`LICENSE`](./LICENSE.md) for more information. - -Maintained by [Yii Software](https://www.yiiframework.com/). diff --git a/docs/internals.md b/docs/internals.md index 8dc4049..087a514 100644 --- a/docs/internals.md +++ b/docs/internals.md @@ -25,7 +25,7 @@ The code is statically analyzed with [Psalm](https://psalm.dev/). To run static ./vendor/bin/psalm ``` -## Rector +## Code style Use [Rector](https://github.com/rectorphp/rector) to make codebase follow some specific rules or use either newest or any specific version of PHP: @@ -34,11 +34,10 @@ use either newest or any specific version of PHP: ./vendor/bin/rector ``` -## Composer require checker +## Dependencies -This package uses [composer-require-checker](https://github.com/maglnet/ComposerRequireChecker) to check if all dependencies are correctly defined in `composer.json`. - -To run the checker, execute the following command: +This package uses [composer-require-checker](https://github.com/maglnet/ComposerRequireChecker) to check if +all dependencies are correctly defined in `composer.json`. To run the checker, execute the following command: ```shell ./vendor/bin/composer-require-checker From 8c4de8c79c29c89ba6a4452fd1e5477948222ca1 Mon Sep 17 00:00:00 2001 From: Luiz Marin <67489841+luizcmarin@users.noreply.github.com> Date: Thu, 23 May 2024 11:40:46 -0300 Subject: [PATCH 3/9] Fix docs (#142) --- CHANGELOG.md | 2 +- README.md | 2 +- composer.json | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6137523..7446c4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Yii debug API Change Log +# Yii Debug API Change Log ## 1.0.0 under development diff --git a/README.md b/README.md index 92dfe39..1da8802 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- + Yii

Yii Debug API


diff --git a/composer.json b/composer.json index b83494e..c4d91da 100644 --- a/composer.json +++ b/composer.json @@ -13,12 +13,22 @@ "license": "BSD-3-Clause", "support": { "issues": "https://github.com/yiisoft/yii-debug-api/issues?state=open", + "source": "https://github.com/yiisoft/yii-debug-api", "forum": "https://www.yiiframework.com/forum/", "wiki": "https://www.yiiframework.com/wiki/", "irc": "ircs://irc.libera.chat:6697/yii", - "chat": "https://t.me/yii3en", - "source": "https://github.com/yiisoft/yii-debug-api" + "chat": "https://t.me/yii3en" }, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/yiisoft" + }, + { + "type": "github", + "url": "https://github.com/sponsors/yiisoft" + } + ], "minimum-stability": "dev", "prefer-stable": true, "require": { From b29b84caadea032dae2a4785d535df827ac642b1 Mon Sep 17 00:00:00 2001 From: Dmitriy Derepko Date: Wed, 29 May 2024 01:50:13 +0300 Subject: [PATCH 4/9] Add tests (#137) * Add tests for DebugHeadersMiddleware * Add tests for ResponseDataWrapperMiddleware * Add tests for DebugApiProvider * Add test for CollectorRepository --- composer.json | 5 +- src/Debug/Provider/DebugApiProvider.php | 3 +- src/Debug/Repository/CollectorRepository.php | 2 +- src/Inspector/ApplicationState.php | 7 +- src/Inspector/Command/BashCommand.php | 2 +- tests/Support/Application/fail.sh | 2 + tests/Support/StubCollector.php | 32 ++++ .../Debug/Middleware/DebugHeadersTest.php | 43 ++++++ .../Middleware/ResponseDataWrapperTest.php | 138 ++++++++++++++++++ .../Debug/Provider/DebugApiProviderTest.php | 36 +++++ .../Repository/CollectorRepositoryTest.php | 100 +++++++++++++ tests/Unit/Inspector/ApplicationStateTest.php | 19 +++ .../Inspector/Command/BashCommandTest.php | 41 ++++++ tests/Unit/Inspector/CommandResponseTest.php | 20 +++ .../Database/DbSchemaProviderTest.php | 2 +- 15 files changed, 444 insertions(+), 8 deletions(-) create mode 100644 tests/Support/Application/fail.sh create mode 100644 tests/Support/StubCollector.php create mode 100644 tests/Unit/Debug/Middleware/DebugHeadersTest.php create mode 100644 tests/Unit/Debug/Middleware/ResponseDataWrapperTest.php create mode 100644 tests/Unit/Debug/Provider/DebugApiProviderTest.php create mode 100644 tests/Unit/Debug/Repository/CollectorRepositoryTest.php create mode 100644 tests/Unit/Inspector/ApplicationStateTest.php create mode 100644 tests/Unit/Inspector/Command/BashCommandTest.php create mode 100644 tests/Unit/Inspector/CommandResponseTest.php rename tests/{ => Unit}/Inspector/Database/DbSchemaProviderTest.php (98%) diff --git a/composer.json b/composer.json index c4d91da..1537463 100644 --- a/composer.json +++ b/composer.json @@ -37,6 +37,7 @@ "gitonomy/gitlib": "^1.3", "guzzlehttp/guzzle": "^7.5", "guzzlehttp/psr7": "^2.4", + "httpsoft/http-message": "^1.1", "psr/container": "^2.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0", @@ -65,12 +66,14 @@ "roave/infection-static-analysis-plugin": "^1.16", "spatie/phpunit-watcher": "^1.23", "vimeo/psalm": "^5.22", - "yiisoft/active-record": "3.0.x-dev", + "yiisoft/active-record": "dev-master", "yiisoft/assets": "^4.0", "yiisoft/csrf": "^2.0", + "yiisoft/db": "1.2 as dev-master", "yiisoft/db-sqlite": "^1.0", "yiisoft/psr-dummy-provider": "^1.0", "yiisoft/router-fastroute": "^3.0", + "yiisoft/test-support": "^3.0", "yiisoft/yii-cycle": "dev-master", "yiisoft/yii-view": "^6.0" }, diff --git a/src/Debug/Provider/DebugApiProvider.php b/src/Debug/Provider/DebugApiProvider.php index d62d5be..2a0977a 100644 --- a/src/Debug/Provider/DebugApiProvider.php +++ b/src/Debug/Provider/DebugApiProvider.php @@ -4,7 +4,6 @@ namespace Yiisoft\Yii\Debug\Api\Debug\Provider; -use Psr\Container\ContainerInterface; use Yiisoft\Di\ServiceProviderInterface; use Yiisoft\Router\RouteCollectorInterface; use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders; @@ -22,7 +21,7 @@ public function getDefinitions(): array public function getExtensions(): array { return [ - RouteCollectorInterface::class => static function (ContainerInterface $container, RouteCollectorInterface $routeCollector) { + RouteCollectorInterface::class => static function (RouteCollectorInterface $routeCollector) { $routeCollector->prependMiddleware(DebugHeaders::class); return $routeCollector; }, diff --git a/src/Debug/Repository/CollectorRepository.php b/src/Debug/Repository/CollectorRepository.php index e37324b..777963e 100644 --- a/src/Debug/Repository/CollectorRepository.php +++ b/src/Debug/Repository/CollectorRepository.php @@ -38,7 +38,7 @@ public function getObject(string $id, string $objectId): array|null $dump = $this->loadData(StorageInterface::TYPE_OBJECTS, $id); foreach ($dump as $name => $value) { - if (($pos = strrpos($name, "#$objectId")) !== false) { + if (($pos = strrpos((string)$name, "#$objectId")) !== false) { return [substr($name, 0, $pos), $value]; } } diff --git a/src/Inspector/ApplicationState.php b/src/Inspector/ApplicationState.php index 9996b20..1b73fd2 100644 --- a/src/Inspector/ApplicationState.php +++ b/src/Inspector/ApplicationState.php @@ -4,7 +4,10 @@ namespace Yiisoft\Yii\Debug\Api\Inspector; -class ApplicationState +/** + * @internal + */ +final class ApplicationState { - public static $params; + public static array $params = []; } diff --git a/src/Inspector/Command/BashCommand.php b/src/Inspector/Command/BashCommand.php index 357e056..9485c99 100644 --- a/src/Inspector/Command/BashCommand.php +++ b/src/Inspector/Command/BashCommand.php @@ -38,7 +38,7 @@ public function run(): CommandResponse ->setTimeout(null) ->run(); - $processOutput = $process->getOutput(); + $processOutput = rtrim($process->getOutput()); if (!$process->getExitCode() > 1) { return new CommandResponse( diff --git a/tests/Support/Application/fail.sh b/tests/Support/Application/fail.sh new file mode 100644 index 0000000..4bbf6fa --- /dev/null +++ b/tests/Support/Application/fail.sh @@ -0,0 +1,2 @@ +echo 'failed' +exit $1 diff --git a/tests/Support/StubCollector.php b/tests/Support/StubCollector.php new file mode 100644 index 0000000..06abc04 --- /dev/null +++ b/tests/Support/StubCollector.php @@ -0,0 +1,32 @@ +data; + } +} diff --git a/tests/Unit/Debug/Middleware/DebugHeadersTest.php b/tests/Unit/Debug/Middleware/DebugHeadersTest.php new file mode 100644 index 0000000..f86459a --- /dev/null +++ b/tests/Unit/Debug/Middleware/DebugHeadersTest.php @@ -0,0 +1,43 @@ +createMock(UrlGeneratorInterface::class); + $urlGenerator->method('generate')->willReturnCallback( + fn (string $route, array $parameters) => $route . '?' . http_build_query($parameters) + ); + $idGenerator = new DebuggerIdGenerator(); + $expectedId = $idGenerator->getId(); + + $middleware = new DebugHeaders($idGenerator, $urlGenerator); + $response = $middleware->process(new ServerRequest(), $this->createRequestHandler()); + + $this->assertSame($expectedId, $response->getHeaderLine('X-Debug-Id')); + $this->assertSame('debug/api/view?id=' . $expectedId, $response->getHeaderLine('X-Debug-Link')); + } + + protected function createRequestHandler(): RequestHandlerInterface + { + return new class () implements RequestHandlerInterface { + public function handle($request): ResponseInterface + { + return new Response(200); + } + }; + } +} diff --git a/tests/Unit/Debug/Middleware/ResponseDataWrapperTest.php b/tests/Unit/Debug/Middleware/ResponseDataWrapperTest.php new file mode 100644 index 0000000..634cc66 --- /dev/null +++ b/tests/Unit/Debug/Middleware/ResponseDataWrapperTest.php @@ -0,0 +1,138 @@ +createMiddleware(); + $response = $middleware->process(new ServerRequest(), $this->createRequestHandler(new Response(200))); + + $this->assertInstanceOf(ResponseInterface::class, $response); + } + + public function testDataResponse(): void + { + $controllerRawResponse = ['id' => 1, 'name' => 'User name']; + $factory = $this->createDataResponseFactory(); + $response = $factory->createResponse($controllerRawResponse); + + $middleware = $this->createMiddleware(); + $response = $middleware->process(new ServerRequest(), $this->createRequestHandler($response)); + + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertInstanceOf(DataResponse::class, $response); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals([ + 'id' => null, + 'data' => $controllerRawResponse, + 'error' => null, + 'success' => true, + ], $response->getData()); + } + + public function testDataResponseErrorStatus(): void + { + $controllerRawResponse = ['id' => 1, 'name' => 'User name']; + $factory = $this->createDataResponseFactory(); + $response = $factory->createResponse($controllerRawResponse, 400); + + $middleware = $this->createMiddleware(); + $response = $middleware->process(new ServerRequest(), $this->createRequestHandler($response)); + + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertInstanceOf(DataResponse::class, $response); + + $this->assertEquals(400, $response->getStatusCode()); + $this->assertEquals([ + 'id' => null, + 'data' => $controllerRawResponse, + 'error' => null, + 'success' => false, + ], $response->getData()); + } + + public function testDataResponseException(): void + { + $errorMessage = 'Test exception'; + $middleware = $this->createMiddleware(); + $response = $middleware->process( + new ServerRequest(), + $this->createExceptionRequestHandler(new NotFoundException($errorMessage)) + ); + + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertInstanceOf(DataResponse::class, $response); + + $this->assertEquals(404, $response->getStatusCode()); + $this->assertEquals([ + 'id' => null, + 'data' => null, + 'error' => $errorMessage, + 'success' => false, + ], $response->getData()); + } + + private function createRequestHandler(ResponseInterface $response): RequestHandlerInterface + { + return new class ($response) implements RequestHandlerInterface { + public function __construct( + private ResponseInterface $response, + ) { + } + + public function handle($request): ResponseInterface + { + return $this->response; + } + }; + } + + private function createExceptionRequestHandler(Throwable $exception): RequestHandlerInterface + { + return new class ($exception) implements RequestHandlerInterface { + public function __construct( + private Throwable $exception, + ) { + } + + public function handle($request): ResponseInterface + { + throw $this->exception; + } + }; + } + + private function createMiddleware(): ResponseDataWrapper + { + $factory = $this->createDataResponseFactory(); + $currentRoute = new CurrentRoute(); + return new ResponseDataWrapper($factory, $currentRoute); + } + + private function createDataResponseFactory(): DataResponseFactory + { + return new DataResponseFactory( + new ResponseFactory(), + new StreamFactory(), + ); + } +} diff --git a/tests/Unit/Debug/Provider/DebugApiProviderTest.php b/tests/Unit/Debug/Provider/DebugApiProviderTest.php new file mode 100644 index 0000000..0ca8861 --- /dev/null +++ b/tests/Unit/Debug/Provider/DebugApiProviderTest.php @@ -0,0 +1,36 @@ +assertIsArray($provider->getDefinitions()); + $this->assertIsArray($provider->getExtensions()); + $this->assertEmpty($provider->getDefinitions()); + + $extensions = $provider->getExtensions(); + $this->assertArrayHasKey(RouteCollectorInterface::class, $extensions); + + $routeCollectorDecorator = $extensions[RouteCollectorInterface::class]; + $this->assertIsCallable($routeCollectorDecorator); + + $routeCollector = $this->createMock(RouteCollectorInterface::class); + $routeCollector->expects($this->once()) + ->method('prependMiddleware') + ->with(DebugHeaders::class) + ->willReturn($routeCollector); + + $this->assertSame($routeCollector, $routeCollectorDecorator($routeCollector)); + } +} diff --git a/tests/Unit/Debug/Repository/CollectorRepositoryTest.php b/tests/Unit/Debug/Repository/CollectorRepositoryTest.php new file mode 100644 index 0000000..b62153b --- /dev/null +++ b/tests/Unit/Debug/Repository/CollectorRepositoryTest.php @@ -0,0 +1,100 @@ + 'value']); + + $storage = $this->createStorage($idGenerator); + $repository = new CollectorRepository($storage); + + $this->assertIsArray($repository->getSummary()); + $this->assertEquals([ + [ + 'id' => $idGenerator->getId(), + 'collectors' => [], + ], + ], $repository->getSummary()); + + $storage->addCollector($stubCollector); + + $this->assertIsArray($repository->getSummary()); + $this->assertEquals([ + [ + 'id' => $idGenerator->getId(), + 'collectors' => [$stubCollector->getName()], + ], + ], $repository->getSummary()); + } + + public function testDetail(): void + { + $idGenerator = new DebuggerIdGenerator(); + $stubCollector = new StubCollector(['key' => 'value']); + + $storage = $this->createStorage($idGenerator); + $storage->addCollector($stubCollector); + + $repository = new CollectorRepository($storage); + + $this->assertIsArray($repository->getDetail($idGenerator->getId())); + $this->assertEquals([ + $stubCollector->getName() => $stubCollector->getCollected(), + ], $repository->getDetail($idGenerator->getId())); + } + + public function testDumpObject(): void + { + $idGenerator = new DebuggerIdGenerator(); + $stubCollector = new StubCollector(['key' => 'value']); + + $storage = $this->createStorage($idGenerator); + $storage->addCollector($stubCollector); + + $repository = new CollectorRepository($storage); + + $this->assertIsArray($repository->getDumpObject($idGenerator->getId())); + $this->assertEquals([ + 'key' => 'value', + ], $repository->getDumpObject($idGenerator->getId())); + } + + public function testObject(): void + { + $idGenerator = new DebuggerIdGenerator(); + + $objectId = '123'; + $stubCollector = new StubCollector([ + 'stdClass#' . $objectId => 'value', + ]); + + $storage = $this->createStorage($idGenerator); + $storage->addCollector($stubCollector); + + $repository = new CollectorRepository($storage); + + $this->assertIsArray($repository->getObject($idGenerator->getId(), $objectId)); + $this->assertEquals([ + 'stdClass', + 'value', + ], $repository->getObject($idGenerator->getId(), $objectId)); + } + + private function createStorage(DebuggerIdGenerator $idGenerator): StorageInterface + { + return new MemoryStorage($idGenerator); + } +} diff --git a/tests/Unit/Inspector/ApplicationStateTest.php b/tests/Unit/Inspector/ApplicationStateTest.php new file mode 100644 index 0000000..2b8aed5 --- /dev/null +++ b/tests/Unit/Inspector/ApplicationStateTest.php @@ -0,0 +1,19 @@ +assertEquals([], ApplicationState::$params); + + ApplicationState::$params = ['key' => 'value']; + $this->assertEquals(['key' => 'value'], ApplicationState::$params); + } +} diff --git a/tests/Unit/Inspector/Command/BashCommandTest.php b/tests/Unit/Inspector/Command/BashCommandTest.php new file mode 100644 index 0000000..5a327f7 --- /dev/null +++ b/tests/Unit/Inspector/Command/BashCommandTest.php @@ -0,0 +1,41 @@ + __DIR__, + ]); + $command = new BashCommand($aliases, ['echo', 'test']); + + $response = $command->run(); + + $this->assertSame(CommandResponse::STATUS_OK, $response->getStatus()); + $this->assertSame('test', $response->getResult()); + $this->assertSame([], $response->getErrors()); + } + + public function testError(): void + { + $aliases = new Aliases([ + '@root' => dirname(__DIR__, 3) . '/Support/Application', + ]); + $command = new BashCommand($aliases, ['bash', 'fail.sh', '1']); + + $response = $command->run(); + + $this->assertSame(CommandResponse::STATUS_ERROR, $response->getStatus()); + $this->assertSame('failed', $response->getResult()); + $this->assertSame([], $response->getErrors()); + } +} diff --git a/tests/Unit/Inspector/CommandResponseTest.php b/tests/Unit/Inspector/CommandResponseTest.php new file mode 100644 index 0000000..68b6428 --- /dev/null +++ b/tests/Unit/Inspector/CommandResponseTest.php @@ -0,0 +1,20 @@ +assertSame(CommandResponse::STATUS_OK, $response->getStatus()); + $this->assertSame('result', $response->getResult()); + $this->assertSame(['errors'], $response->getErrors()); + } +} diff --git a/tests/Inspector/Database/DbSchemaProviderTest.php b/tests/Unit/Inspector/Database/DbSchemaProviderTest.php similarity index 98% rename from tests/Inspector/Database/DbSchemaProviderTest.php rename to tests/Unit/Inspector/Database/DbSchemaProviderTest.php index 0584e09..5a00506 100644 --- a/tests/Inspector/Database/DbSchemaProviderTest.php +++ b/tests/Unit/Inspector/Database/DbSchemaProviderTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Yii\Debug\Api\Tests\Inspector\Database; +namespace Yiisoft\Yii\Debug\Api\Tests\Unit\Inspector\Database; use PHPUnit\Framework\TestCase; use Yiisoft\Cache\NullCache; From 1a391bdbbf0df42661a04f2961cb626d3c39fd04 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Wed, 29 May 2024 01:58:44 +0300 Subject: [PATCH 5/9] Fix broken provider --- src/Debug/Provider/DebugApiProvider.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Debug/Provider/DebugApiProvider.php b/src/Debug/Provider/DebugApiProvider.php index 2a0977a..d62d5be 100644 --- a/src/Debug/Provider/DebugApiProvider.php +++ b/src/Debug/Provider/DebugApiProvider.php @@ -4,6 +4,7 @@ namespace Yiisoft\Yii\Debug\Api\Debug\Provider; +use Psr\Container\ContainerInterface; use Yiisoft\Di\ServiceProviderInterface; use Yiisoft\Router\RouteCollectorInterface; use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders; @@ -21,7 +22,7 @@ public function getDefinitions(): array public function getExtensions(): array { return [ - RouteCollectorInterface::class => static function (RouteCollectorInterface $routeCollector) { + RouteCollectorInterface::class => static function (ContainerInterface $container, RouteCollectorInterface $routeCollector) { $routeCollector->prependMiddleware(DebugHeaders::class); return $routeCollector; }, From 348641434698243e28d48a3e08386b6064a114e6 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Wed, 29 May 2024 02:27:24 +0300 Subject: [PATCH 6/9] Fix routes controller --- src/Inspector/Controller/InspectController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Inspector/Controller/InspectController.php b/src/Inspector/Controller/InspectController.php index 860b3d0..cad40ef 100644 --- a/src/Inspector/Controller/InspectController.php +++ b/src/Inspector/Controller/InspectController.php @@ -307,7 +307,7 @@ public function routes(RouteCollectionInterface $routeCollection): ResponseInter 'methods' => $data['methods'], 'defaults' => $data['defaults'], 'override' => $data['override'], - 'middlewares' => $data['middlewareDefinitions'], + 'middlewares' => $data['middlewareDefinitions'] ?? [], ]; } $response = VarDumper::create($routes)->asPrimitives(5); From ee7e40653661ec61aca70f96a566c31c470a4427 Mon Sep 17 00:00:00 2001 From: Siarhei Bautrukevich Date: Tue, 4 Jun 2024 21:18:20 +0800 Subject: [PATCH 7/9] Fix #143: Add support for `psr/http-message` version `^2.0` --- CHANGELOG.md | 4 ++++ composer.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7446c4f..e6f111c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Yii Debug API Change Log +## 1.0.1 under development + +- Enh #143: Add support for `psr/http-message` version `^2.0` (@bautrukevich) + ## 1.0.0 under development - Initial release. diff --git a/composer.json b/composer.json index 1537463..f3c9455 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "httpsoft/http-message": "^1.1", "psr/container": "^2.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", + "psr/http-message": "^1.0|^2.0", "psr/http-server-handler": "^1.0", "psr/http-server-middleware": "^1.0", "psr/simple-cache": "^2.0|^3.0", From cbb26cef4c7788f5d2373126ed1afac2717bce65 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 4 Jun 2024 22:05:59 +0300 Subject: [PATCH 8/9] Fix CHANGELOG.md (#144) --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6f111c..7446c4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,5 @@ # Yii Debug API Change Log -## 1.0.1 under development - -- Enh #143: Add support for `psr/http-message` version `^2.0` (@bautrukevich) - ## 1.0.0 under development - Initial release. From 9e86aa55c99b414dc45afd958e0ff0f4dc460c63 Mon Sep 17 00:00:00 2001 From: Dmitriy Derepko Date: Fri, 21 Jun 2024 19:50:13 +0300 Subject: [PATCH 9/9] Add debug stuff to application's fallback handler (#145) * Wrap application's fallback handler to provider debug headers * Apply fixes from StyleCI * Ignore class * Fix tests * Refactor * Fix test * Add workaround for Subfolder middleware * Fix tests * Fix tests * Add middleware dispatcher --------- Co-authored-by: StyleCI Bot --- composer-require-checker.json | 1 + composer.json | 1 + config/di-web.php | 12 ++++++ config/params.php | 4 ++ src/Debug/Http/HttpApplicationWrapper.php | 37 +++++++++++++++++++ src/Debug/Http/RouteCollectorWrapper.php | 20 ++++++++++ .../MiddlewareDispatcherMiddleware.php | 24 ++++++++++++ src/Debug/Provider/DebugApiProvider.php | 22 +++++++++-- .../Debug/Provider/DebugApiProviderTest.php | 14 ++++++- 9 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 src/Debug/Http/HttpApplicationWrapper.php create mode 100644 src/Debug/Http/RouteCollectorWrapper.php create mode 100644 src/Debug/Middleware/MiddlewareDispatcherMiddleware.php diff --git a/composer-require-checker.json b/composer-require-checker.json index 23b3346..0528b49 100644 --- a/composer-require-checker.json +++ b/composer-require-checker.json @@ -4,6 +4,7 @@ "Yiisoft\\Assets\\AssetManager", "Yiisoft\\Assets\\AssetPublisherInterface", "Yiisoft\\Yii\\View\\ViewRenderer", + "Yiisoft\\Yii\\Http\\Application", "Codeception\\Event\\FailEvent", "Codeception\\Event\\PrintResultEvent", "Codeception\\Event\\TestEvent", diff --git a/composer.json b/composer.json index f3c9455..9823507 100644 --- a/composer.json +++ b/composer.json @@ -51,6 +51,7 @@ "yiisoft/di": "^1.0", "yiisoft/friendly-exception": "^1.1", "yiisoft/http": "^1.2", + "yiisoft/middleware-dispatcher": "^5.2", "yiisoft/router": "^3.0", "yiisoft/translator": "^3.0", "yiisoft/var-dumper": "^1.4", diff --git a/config/di-web.php b/config/di-web.php index 4836e98..1e17aec 100644 --- a/config/di-web.php +++ b/config/di-web.php @@ -5,6 +5,8 @@ use Cycle\Database\DatabaseProviderInterface; use Psr\Container\ContainerInterface; use Yiisoft\Db\Connection\ConnectionInterface; +use Yiisoft\Yii\Debug\Api\Debug\Http\HttpApplicationWrapper; +use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper; use Yiisoft\Yii\Debug\Api\Debug\Repository\CollectorRepository; use Yiisoft\Yii\Debug\Api\Debug\Repository\CollectorRepositoryInterface; use Yiisoft\Yii\Debug\Api\Inspector\Database\Cycle\CycleSchemaProvider; @@ -34,4 +36,14 @@ ) ); }, + HttpApplicationWrapper::class => [ + '__construct()' => [ + 'middlewareDefinitions' => $params['yiisoft/yii-debug-api']['middlewares'], + ], + ], + RouteCollectorWrapper::class => [ + '__construct()' => [ + 'middlewareDefinitions' => $params['yiisoft/yii-debug-api']['middlewares'], + ], + ], ]; diff --git a/config/params.php b/config/params.php index b6c42ba..9630fc8 100644 --- a/config/params.php +++ b/config/params.php @@ -3,6 +3,7 @@ declare(strict_types=1); use Codeception\Extension; +use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders; use Yiisoft\Yii\Debug\Api\Inspector\Command\CodeceptionCommand; use Yiisoft\Yii\Debug\Api\Inspector\Command\PHPUnitCommand; use Yiisoft\Yii\Debug\Api\Inspector\Command\PsalmCommand; @@ -26,6 +27,9 @@ 'enabled' => true, 'allowedIPs' => ['127.0.0.1', '::1'], 'allowedHosts' => [], + 'middlewares' => [ + DebugHeaders::class, + ], 'inspector' => [ 'commandMap' => [ 'tests' => $testCommands, diff --git a/src/Debug/Http/HttpApplicationWrapper.php b/src/Debug/Http/HttpApplicationWrapper.php new file mode 100644 index 0000000..c3b9b5a --- /dev/null +++ b/src/Debug/Http/HttpApplicationWrapper.php @@ -0,0 +1,37 @@ +middlewareDispatcher; + $middlewareDefinitions = $this->middlewareDefinitions; + + $closure = Closure::bind(static function (Application $application) use ( + $middlewareDispatcher, + $middlewareDefinitions, + ) { + $application->dispatcher = $middlewareDispatcher->withMiddlewares([ + ...$middlewareDefinitions, + ['class' => MiddlewareDispatcherMiddleware::class, '$middlewareDispatcher' => $application->dispatcher], + ]);; + }, null, $application); + + $closure($application); + } +} diff --git a/src/Debug/Http/RouteCollectorWrapper.php b/src/Debug/Http/RouteCollectorWrapper.php new file mode 100644 index 0000000..c31fe75 --- /dev/null +++ b/src/Debug/Http/RouteCollectorWrapper.php @@ -0,0 +1,20 @@ +prependMiddleware(...$this->middlewareDefinitions); + } +} diff --git a/src/Debug/Middleware/MiddlewareDispatcherMiddleware.php b/src/Debug/Middleware/MiddlewareDispatcherMiddleware.php new file mode 100644 index 0000000..4cdaf74 --- /dev/null +++ b/src/Debug/Middleware/MiddlewareDispatcherMiddleware.php @@ -0,0 +1,24 @@ +middlewareDispatcher->dispatch($request, $handler); + } +} diff --git a/src/Debug/Provider/DebugApiProvider.php b/src/Debug/Provider/DebugApiProvider.php index d62d5be..7de2b6a 100644 --- a/src/Debug/Provider/DebugApiProvider.php +++ b/src/Debug/Provider/DebugApiProvider.php @@ -7,7 +7,9 @@ use Psr\Container\ContainerInterface; use Yiisoft\Di\ServiceProviderInterface; use Yiisoft\Router\RouteCollectorInterface; -use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders; +use Yiisoft\Yii\Debug\Api\Debug\Http\HttpApplicationWrapper; +use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper; +use Yiisoft\Yii\Http\Application; final class DebugApiProvider implements ServiceProviderInterface { @@ -22,10 +24,24 @@ public function getDefinitions(): array public function getExtensions(): array { return [ - RouteCollectorInterface::class => static function (ContainerInterface $container, RouteCollectorInterface $routeCollector) { - $routeCollector->prependMiddleware(DebugHeaders::class); + RouteCollectorInterface::class => static function ( + ContainerInterface $container, + RouteCollectorInterface $routeCollector + ) { + /** + * Register debug middlewares twice because a `Subfolder` middleware may rewrite base URL + */ + $routerCollectionWrapper = $container->get(RouteCollectorWrapper::class); + $routerCollectionWrapper->wrap($routeCollector); + return $routeCollector; }, + Application::class => static function (ContainerInterface $container, Application $application) { + $applicationWrapper = $container->get(HttpApplicationWrapper::class); + $applicationWrapper->wrap($application); + + return $application; + }, ]; } } diff --git a/tests/Unit/Debug/Provider/DebugApiProviderTest.php b/tests/Unit/Debug/Provider/DebugApiProviderTest.php index 0ca8861..1d26116 100644 --- a/tests/Unit/Debug/Provider/DebugApiProviderTest.php +++ b/tests/Unit/Debug/Provider/DebugApiProviderTest.php @@ -5,7 +5,9 @@ namespace Yiisoft\Yii\Debug\Api\Tests\Unit\Debug\Provider; use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; use Yiisoft\Router\RouteCollectorInterface; +use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper; use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders; use Yiisoft\Yii\Debug\Api\Debug\Provider\DebugApiProvider; @@ -25,12 +27,20 @@ public function testExtension(): void $routeCollectorDecorator = $extensions[RouteCollectorInterface::class]; $this->assertIsCallable($routeCollectorDecorator); + $middlewares = [DebugHeaders::class]; + + $container = $this->createMock(ContainerInterface::class); + $container->expects($this->once()) + ->method('get') + ->with(RouteCollectorWrapper::class) + ->willReturn(new RouteCollectorWrapper($middlewares)); + $routeCollector = $this->createMock(RouteCollectorInterface::class); $routeCollector->expects($this->once()) ->method('prependMiddleware') - ->with(DebugHeaders::class) + ->with(...$middlewares) ->willReturn($routeCollector); - $this->assertSame($routeCollector, $routeCollectorDecorator($routeCollector)); + $this->assertSame($routeCollector, $routeCollectorDecorator($container, $routeCollector)); } }