From 6cf206e0a299510782edbeee05e6bf1e29bddc09 Mon Sep 17 00:00:00 2001 From: Marcel Pociot Date: Wed, 29 Apr 2020 16:49:33 +0200 Subject: [PATCH] wip --- app/Client/Factory.php | 46 ++-- .../Controllers/AttachDataToLogController.php | 10 +- .../Http}/Controllers/ClearLogsController.php | 5 +- .../Http}/Controllers/DashboardController.php | 3 +- .../Http}/Controllers/LogController.php | 3 +- .../PushLogsToDashboardController.php} | 5 +- .../Http}/Controllers/ReplayLogController.php | 22 +- app/{HttpServer => Http}/App.php | 16 +- .../Controllers/Controller.php | 2 +- .../Controllers/PostController.php | 4 +- app/{HttpServer => Http}/QueryParameters.php | 2 +- app/{Server => }/Http/RouteGenerator.php | 2 +- .../HttpServer.php => Http/Server.php} | 4 +- app/Logger/CliRequestLogger.php | 1 - app/Logger/LoggedRequest.php | 16 +- app/Logger/RequestLogger.php | 11 +- app/Providers/AppServiceProvider.php | 4 +- app/Server/Factory.php | 4 +- .../Admin/DeleteUsersController.php | 2 +- .../Controllers/Admin/ListSitesController.php | 2 +- .../Controllers/Admin/ListUsersController.php | 2 +- .../Controllers/Admin/LoginController.php | 2 +- .../Admin/StoreUsersController.php | 2 +- .../Admin/VerifyLoginController.php | 2 +- .../Controllers/ControlMessageController.php | 2 +- .../Controllers/TunnelMessageController.php | 2 +- app/Server/Http/Router.php | 2 +- composer.json | 2 +- composer.lock | 218 +++++++++--------- tests/Feature/Client/DashboardTest.php | 139 +++++++++++ tests/Feature/Client/TestCase.php | 36 +++ tests/Feature/InspiringCommandTest.php | 20 -- tests/Unit/ExampleTest.php | 18 -- tests/Unit/LoggedRequestTest.php | 48 ++++ tests/Unit/RequestLoggerTest.php | 122 ++++++++++ 35 files changed, 566 insertions(+), 215 deletions(-) rename app/{HttpServer => Client/Http}/Controllers/AttachDataToLogController.php (71%) rename app/{HttpServer => Client/Http}/Controllers/ClearLogsController.php (88%) rename app/{HttpServer => Client/Http}/Controllers/DashboardController.php (89%) rename app/{HttpServer => Client/Http}/Controllers/LogController.php (91%) rename app/{HttpServer/Controllers/StoreLogController.php => Client/Http/Controllers/PushLogsToDashboardController.php} (93%) rename app/{HttpServer => Client/Http}/Controllers/ReplayLogController.php (63%) rename app/{HttpServer => Http}/App.php (66%) rename app/{HttpServer => Http}/Controllers/Controller.php (96%) rename app/{HttpServer => Http}/Controllers/PostController.php (97%) rename app/{HttpServer => Http}/QueryParameters.php (96%) rename app/{Server => }/Http/RouteGenerator.php (98%) rename app/{HttpServer/HttpServer.php => Http/Server.php} (74%) create mode 100755 tests/Feature/Client/DashboardTest.php create mode 100644 tests/Feature/Client/TestCase.php delete mode 100755 tests/Feature/InspiringCommandTest.php delete mode 100644 tests/Unit/ExampleTest.php create mode 100644 tests/Unit/LoggedRequestTest.php create mode 100644 tests/Unit/RequestLoggerTest.php diff --git a/app/Client/Factory.php b/app/Client/Factory.php index a77cf14..46f18cb 100644 --- a/app/Client/Factory.php +++ b/app/Client/Factory.php @@ -2,14 +2,16 @@ namespace App\Client; +use App\Client\Http\Controllers\PushLogsToDashboardController; use App\Client\Http\HttpClient; -use App\HttpServer\App; -use App\HttpServer\Controllers\AttachDataToLogController; -use App\HttpServer\Controllers\ClearLogsController; -use App\HttpServer\Controllers\DashboardController; -use App\HttpServer\Controllers\LogController; -use App\HttpServer\Controllers\ReplayLogController; -use App\HttpServer\Controllers\StoreLogController; +use App\Http\App; +use App\Client\Http\Controllers\AttachDataToLogController; +use App\Client\Http\Controllers\ClearLogsController; +use App\Client\Http\Controllers\DashboardController; +use App\Client\Http\Controllers\LogController; +use App\Client\Http\Controllers\ReplayLogController; +use App\Http\Controllers\StoreLogController; +use App\Http\RouteGenerator; use App\WebSockets\Socket; use Ratchet\WebSocket\WsServer; use React\EventLoop\LoopInterface; @@ -33,9 +35,13 @@ class Factory /** @var App */ protected $app; + /** @var RouteGenerator */ + protected $router; + public function __construct() { $this->loop = LoopFactory::create(); + $this->router = new RouteGenerator(); } public function setHost(string $host) @@ -93,21 +99,18 @@ class Factory protected function addRoutes() { - $dashboardRoute = new Route('/', ['_controller' => app(DashboardController::class)], [], [], null, [], ['GET']); - $logRoute = new Route('/logs', ['_controller' => app(LogController::class)], [], [], null, [], ['GET']); - $storeLogRoute = new Route('/logs', ['_controller' => app(StoreLogController::class)], [], [], null, [], ['POST']); - $replayLogRoute = new Route('/replay/{log}', ['_controller' => app(ReplayLogController::class)], [], [], null, [], ['GET']); - $attachLogDataRoute = new Route('/logs/{request_id}/data', ['_controller' => app(AttachDataToLogController::class)], [], [], null, [], ['POST']); - $clearLogsRoute = new Route('/logs/clear', ['_controller' => app(ClearLogsController::class)], [], [], null, [], ['GET']); + $this->router->get('/', DashboardController::class); + $this->router->get('/logs', LogController::class); + $this->router->post('/logs', PushLogsToDashboardController::class); + $this->router->get('/replay/{log}', ReplayLogController::class); + $this->router->post('/logs/{request_id}/data', AttachDataToLogController::class); + $this->router->post('/logs/clear', ClearLogsController::class); $this->app->route('/socket', new WsServer(new Socket()), ['*']); - $this->app->routes->add('dashboard', $dashboardRoute); - $this->app->routes->add('logs', $logRoute); - $this->app->routes->add('storeLogs', $storeLogRoute); - $this->app->routes->add('replayLog', $replayLogRoute); - $this->app->routes->add('attachLogData', $attachLogDataRoute); - $this->app->routes->add('clearLogs', $clearLogsRoute); + foreach ($this->router->getRoutes()->all() as $name => $route) { + $this->app->routes->add($name, $route); + } } protected function detectNextFreeDashboardPort($port = 4040): int @@ -138,6 +141,11 @@ class Factory return $this; } + public function getApp(): App + { + return $this->app; + } + public function run() { $this->loop->run(); diff --git a/app/HttpServer/Controllers/AttachDataToLogController.php b/app/Client/Http/Controllers/AttachDataToLogController.php similarity index 71% rename from app/HttpServer/Controllers/AttachDataToLogController.php rename to app/Client/Http/Controllers/AttachDataToLogController.php index 0471ab5..6e1ae0d 100644 --- a/app/HttpServer/Controllers/AttachDataToLogController.php +++ b/app/Client/Http/Controllers/AttachDataToLogController.php @@ -1,10 +1,13 @@ setAdditionalData((array)$request->get('data', [])); $this->requestLogger->pushLogs(); + + $httpConnection->send(str(new Response(200))); + return; } + + $httpConnection->send(str(new Response(404))); } } diff --git a/app/HttpServer/Controllers/ClearLogsController.php b/app/Client/Http/Controllers/ClearLogsController.php similarity index 88% rename from app/HttpServer/Controllers/ClearLogsController.php rename to app/Client/Http/Controllers/ClearLogsController.php index 7f53b87..cd06a7f 100644 --- a/app/HttpServer/Controllers/ClearLogsController.php +++ b/app/Client/Http/Controllers/ClearLogsController.php @@ -1,9 +1,10 @@ requestLogger->findLoggedRequest(QueryParameters::create($request)->get('log'))->getRequestData(); + $loggedRequest = $this->requestLogger->findLoggedRequest(QueryParameters::create($request)->get('log')); + + if (is_null($loggedRequest)) { + $connection->send( + str(new Response( + 404, + ['Content-Type' => 'application/json'], + )) + ); + + $connection->close(); + return; + } + + $requestData = $loggedRequest->getRequestData(); /** @var HttpClient $tunnel */ $this->httpClient->performRequest($requestData); diff --git a/app/HttpServer/App.php b/app/Http/App.php similarity index 66% rename from app/HttpServer/App.php rename to app/Http/App.php index d705d39..7f08cfb 100644 --- a/app/HttpServer/App.php +++ b/app/Http/App.php @@ -1,6 +1,6 @@ httpHost = $httpHost; $this->port = $port; - $socket = new Reactor($address.':'.$port, $loop); + $this->socket = new Reactor($address.':'.$port, $loop); $this->routes = new RouteCollection; @@ -25,8 +28,13 @@ class App extends \Ratchet\App $router = new Router($urlMatcher); - $httpServer = new HttpServer($router); + $httpServer = new Server($router); - $this->_server = new IoServer($httpServer, $socket, $loop); + $this->_server = new IoServer($httpServer, $this->socket, $loop); + } + + public function close() + { + $this->socket->close(); } } diff --git a/app/HttpServer/Controllers/Controller.php b/app/Http/Controllers/Controller.php similarity index 96% rename from app/HttpServer/Controllers/Controller.php rename to app/Http/Controllers/Controller.php index 39f30f8..b106514 100644 --- a/app/HttpServer/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -1,6 +1,6 @@ requests->has($loggedRequest->id())) { $this->requests[$loggedRequest->id()] = $loggedRequest; } else { diff --git a/app/Logger/LoggedRequest.php b/app/Logger/LoggedRequest.php index 408d46f..5e5dcfd 100644 --- a/app/Logger/LoggedRequest.php +++ b/app/Logger/LoggedRequest.php @@ -94,6 +94,11 @@ class LoggedRequest implements \JsonSerializable $this->additionalData = array_merge($this->additionalData, $data); } + public function getAdditionalData(): array + { + return $this->additionalData; + } + protected function isBinary(string $string): bool { return preg_match('~[^\x20-\x7E\t\r\n]~', $string) > 0; @@ -122,26 +127,21 @@ class LoggedRequest implements \JsonSerializable } } - public function id() + public function id(): string { return $this->id; } - public function getRequestData() + public function getRequestData(): ?string { return $this->rawRequest; } - public function getResponse() + public function getResponse(): ?Response { return $this->parsedResponse; } - protected function getResponseBody() - { - return \Laminas\Http\Response::fromString($this->rawResponse)->getBody(); - } - protected function getPost() { $postData = []; diff --git a/app/Logger/RequestLogger.php b/app/Logger/RequestLogger.php index 60e6ac8..d214259 100644 --- a/app/Logger/RequestLogger.php +++ b/app/Logger/RequestLogger.php @@ -19,6 +19,8 @@ class RequestLogger /** @var CliRequestLogger */ protected $cliRequestLogger; + const MAX_LOGGED_REQUESTS = 10; + public function __construct(Browser $browser, CliRequestLogger $cliRequestLogger) { $this->client = $browser; @@ -32,17 +34,19 @@ class RequestLogger }); } - public function logRequest(string $rawRequest, Request $request) + public function logRequest(string $rawRequest, Request $request): LoggedRequest { $loggedRequest = new LoggedRequest($rawRequest, $request); array_unshift($this->requests, $loggedRequest); - $this->requests = array_slice($this->requests, 0, 10); + $this->requests = array_slice($this->requests, 0, static::MAX_LOGGED_REQUESTS); $this->cliRequestLogger->logRequest($loggedRequest); $this->pushLogs(); + + return $loggedRequest; } public function logResponse(Request $request, string $rawResponse) @@ -59,7 +63,7 @@ class RequestLogger } } - public function getData() + public function getData(): array { return $this->requests; } @@ -73,6 +77,7 @@ class RequestLogger public function pushLogs() { + // TODO: Make dashboard part configurable $this ->client ->post( diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index ef0c8f5..e49aadf 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -36,7 +36,7 @@ class AppServiceProvider extends ServiceProvider $localConfigFile = getcwd() . DIRECTORY_SEPARATOR . '.expose.php'; if (file_exists($localConfigFile)) { - $localConfig = require_once $localConfigFile; + $localConfig = require $localConfigFile; config()->set('expose', array_merge($builtInConfig, $localConfig)); return; } @@ -49,7 +49,7 @@ class AppServiceProvider extends ServiceProvider ]); if (file_exists($configFile)) { - $globalConfig = require_once $configFile; + $globalConfig = require $configFile; config()->set('expose', array_merge($builtInConfig, $globalConfig)); } } diff --git a/app/Server/Factory.php b/app/Server/Factory.php index fba4170..14e130e 100644 --- a/app/Server/Factory.php +++ b/app/Server/Factory.php @@ -4,7 +4,7 @@ namespace App\Server; use App\Contracts\ConnectionManager as ConnectionManagerContract; use App\Contracts\SubdomainGenerator; -use App\HttpServer\HttpServer; +use App\Http\Server as HttpServer; use App\Server\Connections\ConnectionManager; use App\Server\Http\Controllers\Admin\DeleteUsersController; use App\Server\Http\Controllers\Admin\ListSitesController; @@ -14,7 +14,7 @@ use App\Server\Http\Controllers\Admin\StoreUsersController; use App\Server\Http\Controllers\Admin\VerifyLoginController; use App\Server\Http\Controllers\ControlMessageController; use App\Server\Http\Controllers\TunnelMessageController; -use App\Server\Http\RouteGenerator; +use App\Http\RouteGenerator; use App\Server\Http\Router; use App\Server\SubdomainGenerator\RandomSubdomainGenerator; use Clue\React\SQLite\DatabaseInterface; diff --git a/app/Server/Http/Controllers/Admin/DeleteUsersController.php b/app/Server/Http/Controllers/Admin/DeleteUsersController.php index 3d43f10..5b0c72c 100644 --- a/app/Server/Http/Controllers/Admin/DeleteUsersController.php +++ b/app/Server/Http/Controllers/Admin/DeleteUsersController.php @@ -2,7 +2,7 @@ namespace App\Server\Http\Controllers\Admin; -use App\HttpServer\Controllers\PostController; +use App\Http\Controllers\PostController; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use GuzzleHttp\Psr7\Response; diff --git a/app/Server/Http/Controllers/Admin/ListSitesController.php b/app/Server/Http/Controllers/Admin/ListSitesController.php index c9dd5dc..ef9f7a6 100644 --- a/app/Server/Http/Controllers/Admin/ListSitesController.php +++ b/app/Server/Http/Controllers/Admin/ListSitesController.php @@ -3,7 +3,7 @@ namespace App\Server\Http\Controllers\Admin; use App\Contracts\ConnectionManager; -use App\HttpServer\Controllers\PostController; +use App\Http\Controllers\PostController; use App\Server\Configuration; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; diff --git a/app/Server/Http/Controllers/Admin/ListUsersController.php b/app/Server/Http/Controllers/Admin/ListUsersController.php index bd201db..4dc365a 100644 --- a/app/Server/Http/Controllers/Admin/ListUsersController.php +++ b/app/Server/Http/Controllers/Admin/ListUsersController.php @@ -2,7 +2,7 @@ namespace App\Server\Http\Controllers\Admin; -use App\HttpServer\Controllers\PostController; +use App\Http\Controllers\PostController; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use GuzzleHttp\Psr7\Response; diff --git a/app/Server/Http/Controllers/Admin/LoginController.php b/app/Server/Http/Controllers/Admin/LoginController.php index 79ef5a1..f519aa5 100644 --- a/app/Server/Http/Controllers/Admin/LoginController.php +++ b/app/Server/Http/Controllers/Admin/LoginController.php @@ -3,7 +3,7 @@ namespace App\Server\Http\Controllers\Admin; use App\Contracts\ConnectionManager; -use App\HttpServer\Controllers\PostController; +use App\Http\Controllers\PostController; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use GuzzleHttp\Psr7\Response; diff --git a/app/Server/Http/Controllers/Admin/StoreUsersController.php b/app/Server/Http/Controllers/Admin/StoreUsersController.php index 7a22da3..78f3e6f 100644 --- a/app/Server/Http/Controllers/Admin/StoreUsersController.php +++ b/app/Server/Http/Controllers/Admin/StoreUsersController.php @@ -2,7 +2,7 @@ namespace App\Server\Http\Controllers\Admin; -use App\HttpServer\Controllers\PostController; +use App\Http\Controllers\PostController; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use GuzzleHttp\Psr7\Response; diff --git a/app/Server/Http/Controllers/Admin/VerifyLoginController.php b/app/Server/Http/Controllers/Admin/VerifyLoginController.php index 8e7aa03..26cfc2b 100644 --- a/app/Server/Http/Controllers/Admin/VerifyLoginController.php +++ b/app/Server/Http/Controllers/Admin/VerifyLoginController.php @@ -3,7 +3,7 @@ namespace App\Server\Http\Controllers\Admin; use App\Contracts\ConnectionManager; -use App\HttpServer\Controllers\PostController; +use App\Http\Controllers\PostController; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use GuzzleHttp\Psr7\Response; diff --git a/app/Server/Http/Controllers/ControlMessageController.php b/app/Server/Http/Controllers/ControlMessageController.php index 66a4324..dd196ac 100644 --- a/app/Server/Http/Controllers/ControlMessageController.php +++ b/app/Server/Http/Controllers/ControlMessageController.php @@ -3,7 +3,7 @@ namespace App\Server\Http\Controllers; use App\Contracts\ConnectionManager; -use App\HttpServer\QueryParameters; +use App\Http\QueryParameters; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use Ratchet\WebSocket\MessageComponentInterface; diff --git a/app/Server/Http/Controllers/TunnelMessageController.php b/app/Server/Http/Controllers/TunnelMessageController.php index 3966617..2e7b652 100644 --- a/app/Server/Http/Controllers/TunnelMessageController.php +++ b/app/Server/Http/Controllers/TunnelMessageController.php @@ -3,7 +3,7 @@ namespace App\Server\Http\Controllers; use App\Contracts\ConnectionManager; -use App\HttpServer\Controllers\PostController; +use App\Http\Controllers\PostController; use App\Server\Configuration; use App\Server\Connections\ControlConnection; use GuzzleHttp\Psr7\Response; diff --git a/app/Server/Http/Router.php b/app/Server/Http/Router.php index 6422796..810f1b9 100644 --- a/app/Server/Http/Router.php +++ b/app/Server/Http/Router.php @@ -2,7 +2,7 @@ namespace App\Server\Http; -use App\HttpServer\QueryParameters; +use App\Http\QueryParameters; use GuzzleHttp\Psr7\ServerRequest; use Psr\Http\Message\RequestInterface; use Ratchet\ConnectionInterface; diff --git a/composer.json b/composer.json index ea66c87..e1877b6 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "illuminate/validation": "^7.7", "laminas/laminas-http": "^2.11", "laravel-zero/framework": "^7.0", - "mockery/mockery": "^1.3.1", + "mockery/mockery": "^1.3", "namshi/cuzzle": "^2.0", "nyholm/psr7": "^1.2", "phpunit/phpunit": "^8.5", diff --git a/composer.lock b/composer.lock index a2aaf62..0c53ea3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3199f5982eed399c719f72239be99a83", + "content-hash": "17ed4fb1b80fc6efe2594c3bfbbf3c7f", "packages": [], "packages-dev": [ { @@ -1047,7 +1047,7 @@ }, { "name": "illuminate/cache", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/cache.git", @@ -1098,7 +1098,7 @@ }, { "name": "illuminate/config", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/config.git", @@ -1142,16 +1142,16 @@ }, { "name": "illuminate/console", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/console.git", - "reference": "364648fc102ca0b3a7834934ed5885c11e285f29" + "reference": "3056c8d5069115c0bc86a5dc70b22710d427e259" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/console/zipball/364648fc102ca0b3a7834934ed5885c11e285f29", - "reference": "364648fc102ca0b3a7834934ed5885c11e285f29", + "url": "https://api.github.com/repos/illuminate/console/zipball/3056c8d5069115c0bc86a5dc70b22710d427e259", + "reference": "3056c8d5069115c0bc86a5dc70b22710d427e259", "shasum": "" }, "require": { @@ -1192,20 +1192,20 @@ ], "description": "The Illuminate Console package.", "homepage": "https://laravel.com", - "time": "2020-04-20T09:32:33+00:00" + "time": "2020-04-24T09:01:47+00:00" }, { "name": "illuminate/container", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", - "reference": "aa8dfe90a3eb31dc760adc911647be5d2e129c8a" + "reference": "78a134ab5bcf6e6e50321dfb0d602b698898698d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/aa8dfe90a3eb31dc760adc911647be5d2e129c8a", - "reference": "aa8dfe90a3eb31dc760adc911647be5d2e129c8a", + "url": "https://api.github.com/repos/illuminate/container/zipball/78a134ab5bcf6e6e50321dfb0d602b698898698d", + "reference": "78a134ab5bcf6e6e50321dfb0d602b698898698d", "shasum": "" }, "require": { @@ -1236,20 +1236,20 @@ ], "description": "The Illuminate Container package.", "homepage": "https://laravel.com", - "time": "2020-04-20T14:17:11+00:00" + "time": "2020-04-23T13:57:26+00:00" }, { "name": "illuminate/contracts", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "69a40779d8fc43e3f43da973b9c0c20bdbd81203" + "reference": "4f9cad4bd982e9f100b1f0a42677fdd3bbfa48fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/69a40779d8fc43e3f43da973b9c0c20bdbd81203", - "reference": "69a40779d8fc43e3f43da973b9c0c20bdbd81203", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/4f9cad4bd982e9f100b1f0a42677fdd3bbfa48fd", + "reference": "4f9cad4bd982e9f100b1f0a42677fdd3bbfa48fd", "shasum": "" }, "require": { @@ -1280,11 +1280,11 @@ ], "description": "The Illuminate Contracts package.", "homepage": "https://laravel.com", - "time": "2020-04-09T15:01:22+00:00" + "time": "2020-04-28T07:21:27+00:00" }, { "name": "illuminate/events", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/events.git", @@ -1329,7 +1329,7 @@ }, { "name": "illuminate/filesystem", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/filesystem.git", @@ -1382,16 +1382,16 @@ }, { "name": "illuminate/http", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/http.git", - "reference": "05444c7ecfad9e12c42d75f6b9a3dd0adb8b0a57" + "reference": "d9f6088b0296fa41c0a4afa6a2ec27a156d4917e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/http/zipball/05444c7ecfad9e12c42d75f6b9a3dd0adb8b0a57", - "reference": "05444c7ecfad9e12c42d75f6b9a3dd0adb8b0a57", + "url": "https://api.github.com/repos/illuminate/http/zipball/d9f6088b0296fa41c0a4afa6a2ec27a156d4917e", + "reference": "d9f6088b0296fa41c0a4afa6a2ec27a156d4917e", "shasum": "" }, "require": { @@ -1430,11 +1430,11 @@ ], "description": "The Illuminate Http package.", "homepage": "https://laravel.com", - "time": "2020-04-20T08:03:18+00:00" + "time": "2020-04-24T17:19:43+00:00" }, { "name": "illuminate/pipeline", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/pipeline.git", @@ -1478,7 +1478,7 @@ }, { "name": "illuminate/session", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/session.git", @@ -1529,16 +1529,16 @@ }, { "name": "illuminate/support", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "7143690b5b718a4a89f8a1ecda79833e75dd138c" + "reference": "677a3ad776db92b339a2926927929d0b070642ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/7143690b5b718a4a89f8a1ecda79833e75dd138c", - "reference": "7143690b5b718a4a89f8a1ecda79833e75dd138c", + "url": "https://api.github.com/repos/illuminate/support/zipball/677a3ad776db92b339a2926927929d0b070642ea", + "reference": "677a3ad776db92b339a2926927929d0b070642ea", "shasum": "" }, "require": { @@ -1587,20 +1587,20 @@ ], "description": "The Illuminate Support package.", "homepage": "https://laravel.com", - "time": "2020-04-21T15:58:25+00:00" + "time": "2020-04-28T07:20:41+00:00" }, { "name": "illuminate/testing", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/testing.git", - "reference": "5ec43e2778a5454b31b886f2ed4f4b2d291419fd" + "reference": "8594d186a6a6b9a584043b06d00099b2481f2018" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/testing/zipball/5ec43e2778a5454b31b886f2ed4f4b2d291419fd", - "reference": "5ec43e2778a5454b31b886f2ed4f4b2d291419fd", + "url": "https://api.github.com/repos/illuminate/testing/zipball/8594d186a6a6b9a584043b06d00099b2481f2018", + "reference": "8594d186a6a6b9a584043b06d00099b2481f2018", "shasum": "" }, "require": { @@ -1638,11 +1638,11 @@ ], "description": "The Illuminate Testing package.", "homepage": "https://laravel.com", - "time": "2020-04-16T17:12:54+00:00" + "time": "2020-04-27T14:32:07+00:00" }, { "name": "illuminate/translation", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/translation.git", @@ -1688,16 +1688,16 @@ }, { "name": "illuminate/validation", - "version": "v7.7.1", + "version": "v7.9.2", "source": { "type": "git", "url": "https://github.com/illuminate/validation.git", - "reference": "99377aec3b5a2c2184d99de3dd7c8fb675e5a4ef" + "reference": "24cf7ff8e4a274a42eb86c94796dc01dec9e5760" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/validation/zipball/99377aec3b5a2c2184d99de3dd7c8fb675e5a4ef", - "reference": "99377aec3b5a2c2184d99de3dd7c8fb675e5a4ef", + "url": "https://api.github.com/repos/illuminate/validation/zipball/24cf7ff8e4a274a42eb86c94796dc01dec9e5760", + "reference": "24cf7ff8e4a274a42eb86c94796dc01dec9e5760", "shasum": "" }, "require": { @@ -1737,7 +1737,7 @@ ], "description": "The Illuminate Validation package.", "homepage": "https://laravel.com", - "time": "2020-04-19T19:55:49+00:00" + "time": "2020-04-23T19:11:28+00:00" }, { "name": "jolicode/jolinotif", @@ -2186,16 +2186,16 @@ }, { "name": "laravel-zero/foundation", - "version": "v7.6.1", + "version": "v7.8.1", "source": { "type": "git", "url": "https://github.com/laravel-zero/foundation.git", - "reference": "61438f6d9220d2e20f8610ccbe894507d89f8f1a" + "reference": "eb9fc2275706bdc150fdcc2ff9ec155fc74f7c65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel-zero/foundation/zipball/61438f6d9220d2e20f8610ccbe894507d89f8f1a", - "reference": "61438f6d9220d2e20f8610ccbe894507d89f8f1a", + "url": "https://api.github.com/repos/laravel-zero/foundation/zipball/eb9fc2275706bdc150fdcc2ff9ec155fc74f7c65", + "reference": "eb9fc2275706bdc150fdcc2ff9ec155fc74f7c65", "shasum": "" }, "require": { @@ -2224,7 +2224,7 @@ "framework", "laravel" ], - "time": "2020-04-14T16:39:20+00:00" + "time": "2020-04-27T08:21:33+00:00" }, { "name": "laravel-zero/framework", @@ -3140,24 +3140,21 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", "shasum": "" }, "require": { "php": ">=7.1" }, - "require-dev": { - "phpunit/phpunit": "~6" - }, "type": "library", "extra": { "branch-alias": { @@ -3188,7 +3185,7 @@ "reflection", "static analysis" ], - "time": "2018-08-07T13:53:10+00:00" + "time": "2020-04-27T09:25:28+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -5542,16 +5539,16 @@ }, { "name": "symfony/cache", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "7c229da093cb0c630e5d16b99fd253e20f979ac2" + "reference": "0c5f5b1882dc82b255a4bdead4ed3c7738cddc04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/7c229da093cb0c630e5d16b99fd253e20f979ac2", - "reference": "7c229da093cb0c630e5d16b99fd253e20f979ac2", + "url": "https://api.github.com/repos/symfony/cache/zipball/0c5f5b1882dc82b255a4bdead4ed3c7738cddc04", + "reference": "0c5f5b1882dc82b255a4bdead4ed3c7738cddc04", "shasum": "" }, "require": { @@ -5617,7 +5614,7 @@ "caching", "psr6" ], - "time": "2020-03-27T16:56:45+00:00" + "time": "2020-04-28T17:58:55+00:00" }, { "name": "symfony/cache-contracts", @@ -5679,7 +5676,7 @@ }, { "name": "symfony/console", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", @@ -5755,7 +5752,7 @@ }, { "name": "symfony/error-handler", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", @@ -5810,7 +5807,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -5938,16 +5935,16 @@ }, { "name": "symfony/expression-language", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "00e044885469d193c3b8dfa62030cd4525576d4e" + "reference": "b93755750b9e2a8d240bdf014de5b545105c5178" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/00e044885469d193c3b8dfa62030cd4525576d4e", - "reference": "00e044885469d193c3b8dfa62030cd4525576d4e", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/b93755750b9e2a8d240bdf014de5b545105c5178", + "reference": "b93755750b9e2a8d240bdf014de5b545105c5178", "shasum": "" }, "require": { @@ -5985,11 +5982,11 @@ ], "description": "Symfony ExpressionLanguage Component", "homepage": "https://symfony.com", - "time": "2020-03-27T16:56:45+00:00" + "time": "2020-04-15T15:59:10+00:00" }, { "name": "symfony/finder", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -6038,16 +6035,16 @@ }, { "name": "symfony/http-foundation", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "26fb006a2c7b6cdd23d52157b05f8414ffa417b6" + "reference": "e47fdf8b24edc12022ba52923150ec6484d7f57d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/26fb006a2c7b6cdd23d52157b05f8414ffa417b6", - "reference": "26fb006a2c7b6cdd23d52157b05f8414ffa417b6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e47fdf8b24edc12022ba52923150ec6484d7f57d", + "reference": "e47fdf8b24edc12022ba52923150ec6484d7f57d", "shasum": "" }, "require": { @@ -6089,20 +6086,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2020-03-30T14:14:32+00:00" + "time": "2020-04-18T20:50:06+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "ad574c55d451127cab1c45b4ac51bf283e340cf0" + "reference": "3565e51eecd06106304baba5ccb7ba89db2d7d2b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ad574c55d451127cab1c45b4ac51bf283e340cf0", - "reference": "ad574c55d451127cab1c45b4ac51bf283e340cf0", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3565e51eecd06106304baba5ccb7ba89db2d7d2b", + "reference": "3565e51eecd06106304baba5ccb7ba89db2d7d2b", "shasum": "" }, "require": { @@ -6118,6 +6115,7 @@ "symfony/browser-kit": "<4.4", "symfony/cache": "<5.0", "symfony/config": "<5.0", + "symfony/console": "<4.4", "symfony/dependency-injection": "<4.4", "symfony/doctrine-bridge": "<5.0", "symfony/form": "<5.0", @@ -6185,20 +6183,20 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2020-03-30T15:04:59+00:00" + "time": "2020-04-28T18:53:25+00:00" }, { "name": "symfony/mime", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "481b7d6da88922fb1e0d86a943987722b08f3955" + "reference": "5d6c81c39225a750f3f43bee15f03093fb9aaa0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/481b7d6da88922fb1e0d86a943987722b08f3955", - "reference": "481b7d6da88922fb1e0d86a943987722b08f3955", + "url": "https://api.github.com/repos/symfony/mime/zipball/5d6c81c39225a750f3f43bee15f03093fb9aaa0b", + "reference": "5d6c81c39225a750f3f43bee15f03093fb9aaa0b", "shasum": "" }, "require": { @@ -6247,7 +6245,7 @@ "mime", "mime-type" ], - "time": "2020-03-27T16:56:45+00:00" + "time": "2020-04-17T03:29:44+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6543,16 +6541,16 @@ }, { "name": "symfony/process", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e" + "reference": "3179f68dff5bad14d38c4114a1dab98030801fd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e", - "reference": "c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e", + "url": "https://api.github.com/repos/symfony/process/zipball/3179f68dff5bad14d38c4114a1dab98030801fd7", + "reference": "3179f68dff5bad14d38c4114a1dab98030801fd7", "shasum": "" }, "require": { @@ -6588,7 +6586,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2020-03-27T16:56:45+00:00" + "time": "2020-04-15T15:59:10+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -6656,16 +6654,16 @@ }, { "name": "symfony/routing", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "d98a95d0a684caba47a47c1c50c602a669dc973b" + "reference": "9b18480a6e101f8d9ab7c483ace7c19441be5111" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/d98a95d0a684caba47a47c1c50c602a669dc973b", - "reference": "d98a95d0a684caba47a47c1c50c602a669dc973b", + "url": "https://api.github.com/repos/symfony/routing/zipball/9b18480a6e101f8d9ab7c483ace7c19441be5111", + "reference": "9b18480a6e101f8d9ab7c483ace7c19441be5111", "shasum": "" }, "require": { @@ -6728,7 +6726,7 @@ "uri", "url" ], - "time": "2020-03-30T11:42:42+00:00" + "time": "2020-04-21T21:02:50+00:00" }, { "name": "symfony/service-contracts", @@ -6790,16 +6788,16 @@ }, { "name": "symfony/translation", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "99b831770e10807dca0979518e2c89edffef5978" + "reference": "c3879db7a68fe3e12b41263b05879412c87b27fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/99b831770e10807dca0979518e2c89edffef5978", - "reference": "99b831770e10807dca0979518e2c89edffef5978", + "url": "https://api.github.com/repos/symfony/translation/zipball/c3879db7a68fe3e12b41263b05879412c87b27fd", + "reference": "c3879db7a68fe3e12b41263b05879412c87b27fd", "shasum": "" }, "require": { @@ -6863,7 +6861,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2020-03-27T16:56:45+00:00" + "time": "2020-04-12T16:45:47+00:00" }, { "name": "symfony/translation-contracts", @@ -6924,16 +6922,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "f74a126acd701392eef2492a17228d42552c86b5" + "reference": "09de28632f16f81058a85fcf318397218272a07b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/f74a126acd701392eef2492a17228d42552c86b5", - "reference": "f74a126acd701392eef2492a17228d42552c86b5", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/09de28632f16f81058a85fcf318397218272a07b", + "reference": "09de28632f16f81058a85fcf318397218272a07b", "shasum": "" }, "require": { @@ -6995,20 +6993,20 @@ "debug", "dump" ], - "time": "2020-03-27T16:56:45+00:00" + "time": "2020-04-12T16:45:47+00:00" }, { "name": "symfony/var-exporter", - "version": "v5.0.7", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "ffd29a70370e466343e33154b5df197a07a13afa" + "reference": "5d18811da9e1ae2bb86b0a97fb2d784e27ffd59f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/ffd29a70370e466343e33154b5df197a07a13afa", - "reference": "ffd29a70370e466343e33154b5df197a07a13afa", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5d18811da9e1ae2bb86b0a97fb2d784e27ffd59f", + "reference": "5d18811da9e1ae2bb86b0a97fb2d784e27ffd59f", "shasum": "" }, "require": { @@ -7055,7 +7053,7 @@ "instantiate", "serialize" ], - "time": "2020-03-27T16:56:45+00:00" + "time": "2020-04-15T15:59:10+00:00" }, { "name": "theseer/tokenizer", diff --git a/tests/Feature/Client/DashboardTest.php b/tests/Feature/Client/DashboardTest.php new file mode 100755 index 0000000..9d9355c --- /dev/null +++ b/tests/Feature/Client/DashboardTest.php @@ -0,0 +1,139 @@ +browser = new Browser($this->loop); + $this->requestLogger = $this->app->make(RequestLogger::class); + } + + public function tearDown(): void + { + parent::tearDown(); + + $this->dashboardFactory->getApp()->close(); + } + + /** @test */ + public function accessing_the_dashboard_works() + { + $this->startDashboard(); + + /** @var ResponseInterface $response */ + $response = $this->await($this->browser->get('http://127.0.0.1:4040')); + + $this->assertSame(200, $response->getStatusCode()); + } + + /** @test */ + public function it_can_replay_requests() + { + $request = new Request('GET', '/example', [ + 'X-Expose-Request-ID' => 'request-one' + ]); + + $httpClient = m::mock(HttpClient::class); + $httpClient->shouldReceive('performRequest') + ->once() + ->with(str($request)); + + app()->instance(HttpClient::class, $httpClient); + + $this->startDashboard(); + + $this->logRequest($request); + + $this->assertSame(200, + $this->await($this->browser->get("http://127.0.0.1:4040/replay/request-one")) + ->getStatusCode() + ); + } + + /** @test */ + public function it_returns_404_for_non_existing_replay_logs() + { + $this->startDashboard(); + + $this->expectException(ResponseException::class); + $this->expectExceptionMessage(404); + + $this->await($this->browser->get("http://127.0.0.1:4040/replay/invalid-request")); + } + + /** @test */ + public function it_can_clear_logs() + { + $this->startDashboard(); + + $this->logRequest(new Request('GET', '/foo')); + $this->logRequest(new Request('POST', '/bar')); + $this->logRequest(new Request('DELETE', '/baz')); + + $this->assertCount(3, $this->requestLogger->getData()); + + $this->await($this->browser->get("http://127.0.0.1:4040/logs/clear")); + + $this->assertCount(0, $this->requestLogger->getData()); + } + + /** @test */ + public function it_can_attach_additional_data_to_requests() + { + $this->startDashboard(); + + $loggedRequest = $this->logRequest(new Request('GET', '/foo')); + + $this->await($this->browser->post("http://127.0.0.1:4040/logs/{$loggedRequest->id()}/data", [ + 'Content-Type' => 'application/json' + ], json_encode([ + 'data' => [ + 'foo' => 'bar', + ] + ]))); + + $this->assertSame([ + 'foo' => 'bar' + ], $this->requestLogger->findLoggedRequest($loggedRequest->id())->getAdditionalData()); + } + + protected function logRequest(RequestInterface $request): LoggedRequest + { + return $this->requestLogger->logRequest(str($request), \Laminas\Http\Request::fromString(str($request))); + } + + protected function startDashboard() + { + $this->dashboardFactory = (new Factory()) + ->setLoop($this->loop) + ->createHttpServer(); + } +} diff --git a/tests/Feature/Client/TestCase.php b/tests/Feature/Client/TestCase.php new file mode 100644 index 0000000..19e9492 --- /dev/null +++ b/tests/Feature/Client/TestCase.php @@ -0,0 +1,36 @@ +app->bind(ConsoleOutputInterface::class, function() { + return new ConsoleOutput(); + }); + + /** @var LoopInterface $loop */ + $this->loop = $this->app->make(LoopInterface::class); + } + + protected function await(PromiseInterface $promise, LoopInterface $loop = null, $timeout = null) + { + return await($promise, $loop ?? $this->loop, $timeout ?? static::AWAIT_TIMEOUT); + } +} diff --git a/tests/Feature/InspiringCommandTest.php b/tests/Feature/InspiringCommandTest.php deleted file mode 100755 index 358e77b..0000000 --- a/tests/Feature/InspiringCommandTest.php +++ /dev/null @@ -1,20 +0,0 @@ -artisan('inspiring') - ->expectsOutput('Simplicity is the ultimate sophistication.') - ->assertExitCode(0); - } -} diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php deleted file mode 100644 index 0c5acb6..0000000 --- a/tests/Unit/ExampleTest.php +++ /dev/null @@ -1,18 +0,0 @@ -assertTrue(true); - } -} diff --git a/tests/Unit/LoggedRequestTest.php b/tests/Unit/LoggedRequestTest.php new file mode 100644 index 0000000..c90d6c3 --- /dev/null +++ b/tests/Unit/LoggedRequestTest.php @@ -0,0 +1,48 @@ + 'example-request' + ])); + $parsedRequest = LaminasRequest::fromString($rawRequest); + + $loggedRequest = new LoggedRequest($rawRequest, $parsedRequest); + $this->assertSame('example-request', $loggedRequest->id()); + } + + /** @test */ + public function it_returns_the_raw_request() + { + $rawRequest = str(new Request(200, '/expose', [ + 'X-Expose-Request-ID' => 'example-request' + ])); + $parsedRequest = LaminasRequest::fromString($rawRequest); + + $loggedRequest = new LoggedRequest($rawRequest, $parsedRequest); + $this->assertSame($rawRequest, $loggedRequest->getRequestData()); + } + + /** @test */ + public function it_returns_the_parsed_request() + { + $rawRequest = str(new Request(200, '/expose', [ + 'X-Expose-Request-ID' => 'example-request' + ])); + $parsedRequest = LaminasRequest::fromString($rawRequest); + + $loggedRequest = new LoggedRequest($rawRequest, $parsedRequest); + $this->assertSame($parsedRequest, $loggedRequest->getRequest()); + } +} diff --git a/tests/Unit/RequestLoggerTest.php b/tests/Unit/RequestLoggerTest.php new file mode 100644 index 0000000..3cbde73 --- /dev/null +++ b/tests/Unit/RequestLoggerTest.php @@ -0,0 +1,122 @@ +shouldReceive('post') + ->once(); + + $cliLogger = m::mock(CliRequestLogger::class); + $cliLogger->shouldReceive('logRequest')->once(); + + $requestString = str(new Request(200, '/example')); + $parsedRequest = LaminasRequest::fromString($requestString); + + $logger = new RequestLogger($browser, $cliLogger); + $logger->logRequest($requestString, $parsedRequest); + + $this->assertCount(1, $logger->getData()); + } + + /** @test */ + public function it_can_clear_the_requests() + { + $browser = m::mock(Browser::class); + $browser->shouldReceive('post') + ->twice(); + + $cliLogger = m::mock(CliRequestLogger::class); + $cliLogger->shouldReceive('logRequest')->once(); + + $requestString = str(new Request(200, '/example')); + $parsedRequest = LaminasRequest::fromString($requestString); + + $logger = new RequestLogger($browser, $cliLogger); + $logger->logRequest($requestString, $parsedRequest); + + $logger->clear(); + + $this->assertCount(0, $logger->getData()); + } + + /** @test */ + public function it_can_associate_a_response_with_a_request() + { + $browser = m::mock(Browser::class); + $browser->shouldReceive('post') + ->twice(); + + $cliLogger = m::mock(CliRequestLogger::class); + $cliLogger->shouldReceive('logRequest') + ->twice(); + + $requestString = str(new Request(200, '/example')); + $parsedRequest = LaminasRequest::fromString($requestString); + + $logger = new RequestLogger($browser, $cliLogger); + $loggedRequest = $logger->logRequest($requestString, $parsedRequest); + + $this->assertNull($logger->findLoggedRequest($loggedRequest->id())->getResponse()); + + $responseString = str(new Response(200, [], 'Hello World!')); + + $logger->logResponse($parsedRequest, $responseString); + + $this->assertNotNull($logger->findLoggedRequest($loggedRequest->id())->getResponse()); + } + + /** @test */ + public function it_can_find_a_request_by_id() + { + $browser = m::mock(Browser::class); + $browser->shouldReceive('post') + ->once(); + + $cliLogger = m::mock(CliRequestLogger::class); + $cliLogger->shouldReceive('logRequest')->once(); + + $requestString = str(new Request(200, '/example')); + $parsedRequest = LaminasRequest::fromString($requestString); + + $logger = new RequestLogger($browser, $cliLogger); + $loggedRequest = $logger->logRequest($requestString, $parsedRequest); + + $this->assertSame($loggedRequest, $logger->findLoggedRequest($loggedRequest->id())); + } + + /** @test */ + public function it_only_stores_a_limited_amount_of_requests() + { + $browser = m::mock(Browser::class); + $browser->shouldReceive('post'); + + $cliLogger = m::mock(CliRequestLogger::class); + $cliLogger->shouldReceive('logRequest'); + + $requestString = str(new Request(200, '/example')); + $parsedRequest = LaminasRequest::fromString($requestString); + + $logger = new RequestLogger($browser, $cliLogger); + + foreach (range(1, 20) as $i) { + $logger->logRequest($requestString, $parsedRequest); + } + + $this->assertCount(RequestLogger::MAX_LOGGED_REQUESTS, $logger->getData()); + } +}