more tests #19

Merged
rrise merged 5 commits from chore/more-tests-jwt into master 2025-11-16 16:40:12 +00:00
17 changed files with 830 additions and 85 deletions

View File

@@ -5,7 +5,7 @@
<option name="interpreterName" value="composer-runtime" /> <option name="interpreterName" value="composer-runtime" />
</PhpTestInterpreterSettings> </PhpTestInterpreterSettings>
</CommandLine> </CommandLine>
<TestRunner configuration_file="$PROJECT_DIR$/phpunit.xml" scope="XML" use_alternative_configuration_file="true" /> <TestRunner configuration_file="$PROJECT_DIR$/phpunit.xml" coverage_engine="PCov" scope="XML" use_alternative_configuration_file="true" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -21,12 +21,14 @@
"lcobucci/jwt": "^5.6", "lcobucci/jwt": "^5.6",
"adhocore/cli": "^1.9", "adhocore/cli": "^1.9",
"robinvdvleuten/ulid": "^5.0", "robinvdvleuten/ulid": "^5.0",
"monolog/monolog": "^3.9" "monolog/monolog": "^3.9",
"react/promise": "^3",
"react/async": "^4"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^12.4", "phpunit/phpunit": "^12.4",
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"squizlabs/php_codesniffer": "^3.12", "squizlabs/php_codesniffer": "^4.0",
"lendable/composer-license-checker": "^1.2", "lendable/composer-license-checker": "^1.2",
"phpstan/phpstan": "^2.1.31", "phpstan/phpstan": "^2.1.31",
"kwn/php-rdkafka-stubs": "^2.2" "kwn/php-rdkafka-stubs": "^2.2"

305
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "7c2d40400d6f4d0469324dc1645eba3c", "content-hash": "856fdd307835b635e6e912a2d5028515",
"packages": [ "packages": [
{ {
"name": "adhocore/cli", "name": "adhocore/cli",
@@ -300,16 +300,16 @@
}, },
{ {
"name": "google/protobuf", "name": "google/protobuf",
"version": "v4.33.0", "version": "v4.33.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/protocolbuffers/protobuf-php.git", "url": "https://github.com/protocolbuffers/protobuf-php.git",
"reference": "b50269e23204e5ae859a326ec3d90f09efe3047d" "reference": "0cd73ccf0cd26c3e72299cce1ea6144091a57e12"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/b50269e23204e5ae859a326ec3d90f09efe3047d", "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/0cd73ccf0cd26c3e72299cce1ea6144091a57e12",
"reference": "b50269e23204e5ae859a326ec3d90f09efe3047d", "reference": "0cd73ccf0cd26c3e72299cce1ea6144091a57e12",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -338,13 +338,13 @@
"proto" "proto"
], ],
"support": { "support": {
"source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.0" "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.1"
}, },
"time": "2025-10-15T20:10:28+00:00" "time": "2025-11-12T21:58:05+00:00"
}, },
{ {
"name": "illuminate/collections", "name": "illuminate/collections",
"version": "v12.38.0", "version": "v12.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/collections.git", "url": "https://github.com/illuminate/collections.git",
@@ -403,7 +403,7 @@
}, },
{ {
"name": "illuminate/conditionable", "name": "illuminate/conditionable",
"version": "v12.38.0", "version": "v12.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/conditionable.git", "url": "https://github.com/illuminate/conditionable.git",
@@ -449,7 +449,7 @@
}, },
{ {
"name": "illuminate/container", "name": "illuminate/container",
"version": "v12.38.0", "version": "v12.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/container.git", "url": "https://github.com/illuminate/container.git",
@@ -510,7 +510,7 @@
}, },
{ {
"name": "illuminate/contracts", "name": "illuminate/contracts",
"version": "v12.38.0", "version": "v12.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/contracts.git", "url": "https://github.com/illuminate/contracts.git",
@@ -558,7 +558,7 @@
}, },
{ {
"name": "illuminate/database", "name": "illuminate/database",
"version": "v12.38.0", "version": "v12.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/database.git", "url": "https://github.com/illuminate/database.git",
@@ -629,7 +629,7 @@
}, },
{ {
"name": "illuminate/macroable", "name": "illuminate/macroable",
"version": "v12.38.0", "version": "v12.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/macroable.git", "url": "https://github.com/illuminate/macroable.git",
@@ -675,7 +675,7 @@
}, },
{ {
"name": "illuminate/support", "name": "illuminate/support",
"version": "v12.38.0", "version": "v12.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/support.git", "url": "https://github.com/illuminate/support.git",
@@ -1798,6 +1798,226 @@
}, },
"time": "2021-10-29T13:26:27+00:00" "time": "2021-10-29T13:26:27+00:00"
}, },
{
"name": "react/async",
"version": "v4.3.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/async.git",
"reference": "635d50e30844a484495713e8cb8d9e079c0008a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/async/zipball/635d50e30844a484495713e8cb8d9e079c0008a5",
"reference": "635d50e30844a484495713e8cb8d9e079c0008a5",
"shasum": ""
},
"require": {
"php": ">=8.1",
"react/event-loop": "^1.2",
"react/promise": "^3.2 || ^2.8 || ^1.2.1"
},
"require-dev": {
"phpstan/phpstan": "1.10.39",
"phpunit/phpunit": "^9.6"
},
"type": "library",
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"React\\Async\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Lück",
"email": "christian@clue.engineering",
"homepage": "https://clue.engineering/"
},
{
"name": "Cees-Jan Kiewiet",
"email": "reactphp@ceesjankiewiet.nl",
"homepage": "https://wyrihaximus.net/"
},
{
"name": "Jan Sorgalla",
"email": "jsorgalla@gmail.com",
"homepage": "https://sorgalla.com/"
},
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"homepage": "https://cboden.dev/"
}
],
"description": "Async utilities and fibers for ReactPHP",
"keywords": [
"async",
"reactphp"
],
"support": {
"issues": "https://github.com/reactphp/async/issues",
"source": "https://github.com/reactphp/async/tree/v4.3.0"
},
"funding": [
{
"url": "https://opencollective.com/reactphp",
"type": "open_collective"
}
],
"time": "2024-06-04T14:40:02+00:00"
},
{
"name": "react/event-loop",
"version": "v1.5.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/event-loop.git",
"reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354",
"reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
},
"suggest": {
"ext-pcntl": "For signal handling support when using the StreamSelectLoop"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\EventLoop\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Lück",
"email": "christian@clue.engineering",
"homepage": "https://clue.engineering/"
},
{
"name": "Cees-Jan Kiewiet",
"email": "reactphp@ceesjankiewiet.nl",
"homepage": "https://wyrihaximus.net/"
},
{
"name": "Jan Sorgalla",
"email": "jsorgalla@gmail.com",
"homepage": "https://sorgalla.com/"
},
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"homepage": "https://cboden.dev/"
}
],
"description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.",
"keywords": [
"asynchronous",
"event-loop"
],
"support": {
"issues": "https://github.com/reactphp/event-loop/issues",
"source": "https://github.com/reactphp/event-loop/tree/v1.5.0"
},
"funding": [
{
"url": "https://opencollective.com/reactphp",
"type": "open_collective"
}
],
"time": "2023-11-13T13:48:05+00:00"
},
{
"name": "react/promise",
"version": "v3.3.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
"reference": "23444f53a813a3296c1368bb104793ce8d88f04a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a",
"reference": "23444f53a813a3296c1368bb104793ce8d88f04a",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
},
"require-dev": {
"phpstan/phpstan": "1.12.28 || 1.4.10",
"phpunit/phpunit": "^9.6 || ^7.5"
},
"type": "library",
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"React\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jan Sorgalla",
"email": "jsorgalla@gmail.com",
"homepage": "https://sorgalla.com/"
},
{
"name": "Christian Lück",
"email": "christian@clue.engineering",
"homepage": "https://clue.engineering/"
},
{
"name": "Cees-Jan Kiewiet",
"email": "reactphp@ceesjankiewiet.nl",
"homepage": "https://wyrihaximus.net/"
},
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"homepage": "https://cboden.dev/"
}
],
"description": "A lightweight implementation of CommonJS Promises/A for PHP",
"keywords": [
"promise",
"promises"
],
"support": {
"issues": "https://github.com/reactphp/promise/issues",
"source": "https://github.com/reactphp/promise/tree/v3.3.0"
},
"funding": [
{
"url": "https://opencollective.com/reactphp",
"type": "open_collective"
}
],
"time": "2025-08-19T18:57:03+00:00"
},
{ {
"name": "roadrunner-php/app-logger", "name": "roadrunner-php/app-logger",
"version": "1.2.0", "version": "1.2.0",
@@ -2150,16 +2370,16 @@
}, },
{ {
"name": "spiral/roadrunner", "name": "spiral/roadrunner",
"version": "v2025.1.4", "version": "v2025.1.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/roadrunner-server/roadrunner.git", "url": "https://github.com/roadrunner-server/roadrunner.git",
"reference": "ff25363b72dd6ab2bd642d741db13b30d52d254f" "reference": "d68bee29eb689c5310f8ede935c95a13bd7cc153"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/roadrunner-server/roadrunner/zipball/ff25363b72dd6ab2bd642d741db13b30d52d254f", "url": "https://api.github.com/repos/roadrunner-server/roadrunner/zipball/d68bee29eb689c5310f8ede935c95a13bd7cc153",
"reference": "ff25363b72dd6ab2bd642d741db13b30d52d254f", "reference": "d68bee29eb689c5310f8ede935c95a13bd7cc153",
"shasum": "" "shasum": ""
}, },
"type": "metapackage", "type": "metapackage",
@@ -2185,10 +2405,9 @@
"homepage": "https://roadrunner.dev/", "homepage": "https://roadrunner.dev/",
"support": { "support": {
"chat": "https://discord.gg/V6EK4he", "chat": "https://discord.gg/V6EK4he",
"docs": "https://roadrunner.dev/docs", "docs": "https://docs.roadrunner.dev/",
"forum": "https://forum.roadrunner.dev/",
"issues": "https://github.com/roadrunner-server/roadrunner/issues", "issues": "https://github.com/roadrunner-server/roadrunner/issues",
"source": "https://github.com/roadrunner-server/roadrunner/tree/v2025.1.4" "source": "https://github.com/roadrunner-server/roadrunner/tree/v2025.1.5"
}, },
"funding": [ "funding": [
{ {
@@ -2196,7 +2415,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-10-02T16:43:06+00:00" "time": "2025-11-13T17:24:29+00:00"
}, },
{ {
"name": "spiral/roadrunner-http", "name": "spiral/roadrunner-http",
@@ -3952,16 +4171,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "12.4.2", "version": "12.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "a94ea4d26d865875803b23aaf78c3c2c670ea2ea" "reference": "d8f644d8d9bb904867f7a0aeb1bd306e0d966949"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a94ea4d26d865875803b23aaf78c3c2c670ea2ea", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d8f644d8d9bb904867f7a0aeb1bd306e0d966949",
"reference": "a94ea4d26d865875803b23aaf78c3c2c670ea2ea", "reference": "d8f644d8d9bb904867f7a0aeb1bd306e0d966949",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4029,7 +4248,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.2" "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -4053,7 +4272,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-10-30T08:41:39+00:00" "time": "2025-11-13T07:20:26+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
@@ -4954,26 +5173,26 @@
}, },
{ {
"name": "squizlabs/php_codesniffer", "name": "squizlabs/php_codesniffer",
"version": "3.13.5", "version": "4.0.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
"reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" "reference": "0525c73950de35ded110cffafb9892946d7771b5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0525c73950de35ded110cffafb9892946d7771b5",
"reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "reference": "0525c73950de35ded110cffafb9892946d7771b5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-simplexml": "*", "ext-simplexml": "*",
"ext-tokenizer": "*", "ext-tokenizer": "*",
"ext-xmlwriter": "*", "ext-xmlwriter": "*",
"php": ">=5.4.0" "php": ">=7.2.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31"
}, },
"bin": [ "bin": [
"bin/phpcbf", "bin/phpcbf",
@@ -4998,7 +5217,7 @@
"homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
} }
], ],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
"keywords": [ "keywords": [
"phpcs", "phpcs",
@@ -5029,7 +5248,7 @@
"type": "thanks_dev" "type": "thanks_dev"
} }
], ],
"time": "2025-11-04T16:30:35+00:00" "time": "2025-11-10T16:43:36+00:00"
}, },
{ {
"name": "staabm/side-effects-detector", "name": "staabm/side-effects-detector",
@@ -5675,16 +5894,16 @@
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",
"version": "1.2.3", "version": "1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/theseer/tokenizer.git", "url": "https://github.com/theseer/tokenizer.git",
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb",
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5713,7 +5932,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": { "support": {
"issues": "https://github.com/theseer/tokenizer/issues", "issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.3" "source": "https://github.com/theseer/tokenizer/tree/1.3.0"
}, },
"funding": [ "funding": [
{ {
@@ -5721,7 +5940,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-03-03T12:36:25+00:00" "time": "2025-11-13T13:44:09+00:00"
} }
], ],
"aliases": [], "aliases": [],
@@ -5733,5 +5952,5 @@
"php": "^8.4" "php": "^8.4"
}, },
"platform-dev": {}, "platform-dev": {},
"plugin-api-version": "2.6.0" "plugin-api-version": "2.9.0"
} }

View File

@@ -4,6 +4,10 @@ use Siteworxpro\App\Helpers\Env;
return [ return [
'app' => [
'log_level' => Env::get('LOG_LEVEL', 'debug'),
],
/** /**
* The server configuration. * The server configuration.
*/ */

View File

@@ -9,6 +9,9 @@ use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Siteworxpro\App\Attributes\Events\ListensFor; use Siteworxpro\App\Attributes\Events\ListensFor;
use function React\Async\await;
use function React\Async\coroutine;
/** /**
* Class Dispatcher * Class Dispatcher
* *
@@ -29,6 +32,8 @@ class Dispatcher implements DispatcherContract, Arrayable
*/ */
private Collection $pushed; private Collection $pushed;
private array $subscribers = [];
/** /**
* @var string LISTENERS_NAMESPACE The namespace where listeners are located * @var string LISTENERS_NAMESPACE The namespace where listeners are located
*/ */
@@ -99,7 +104,7 @@ class Dispatcher implements DispatcherContract, Arrayable
*/ */
public function subscribe($subscriber): void public function subscribe($subscriber): void
{ {
$this->listeners = array_merge($this->listeners, (array) $subscriber); $this->subscribers[] = $subscriber;
} }
/** /**
@@ -108,6 +113,7 @@ class Dispatcher implements DispatcherContract, Arrayable
* @param $event * @param $event
* @param array $payload * @param array $payload
* @return array|null * @return array|null
* @throws \Throwable
*/ */
public function until($event, $payload = []): array|null public function until($event, $payload = []): array|null
{ {
@@ -121,6 +127,7 @@ class Dispatcher implements DispatcherContract, Arrayable
* @param array $payload * @param array $payload
* @param bool $halt * @param bool $halt
* @return array|null * @return array|null
* @throws \Throwable
*/ */
public function dispatch($event, $payload = [], $halt = false): array|null public function dispatch($event, $payload = [], $halt = false): array|null
{ {
@@ -130,23 +137,46 @@ class Dispatcher implements DispatcherContract, Arrayable
$eventClass = $event; $eventClass = $event;
} }
// Handle subscribers as a coroutine
$promise = coroutine(function () use ($event, $payload, $halt, $eventClass, &$responses) {
foreach ($this->subscribers as $subscriber) {
if (method_exists($subscriber, 'handle')) {
$response = $subscriber->handle($event, $payload);
$responses[$eventClass] = $response;
if ($halt && $response !== null) {
return $responses;
}
}
}
return null;
});
$listeners = $this->listeners[$eventClass] ?? null; $listeners = $this->listeners[$eventClass] ?? null;
// If no listeners, just await the subscriber promise
if ($listeners === null) { if ($listeners === null) {
return null; return await($promise);
} }
$responses = []; $responses = [];
foreach ($listeners as $listener) { foreach ($listeners as $listener) {
$response = $listener($event, $payload); $response = $listener($event, $payload);
$responses[] = $response; $responses[$eventClass] = $response;
if ($halt && $response !== null) { if ($halt && $response !== null) {
return $response; return $response;
} }
} }
// Await the subscriber promise and merge responses
$promiseResponses = await($promise);
if (is_array($promiseResponses)) {
$responses = array_merge($responses, $promiseResponses);
}
return $responses; return $responses;
} }
@@ -167,6 +197,7 @@ class Dispatcher implements DispatcherContract, Arrayable
* *
* @param $event * @param $event
* @return void * @return void
* @throws \Throwable
*/ */
public function flush($event): void public function flush($event): void
{ {

View File

@@ -18,12 +18,15 @@ use Siteworxpro\App\Services\Facades\Logger;
class Connected extends Listener class Connected extends Listener
{ {
/** /**
* @param ConnectionEvent $event * @param mixed $event
* @param array $payload * @param array $payload
* @return null * @return null
*/ */
public function __invoke($event, array $payload = []): null public function __invoke(mixed $event, array $payload = []): null
{ {
if (!($event instanceof ConnectionEvent)) {
throw new \TypeError("Invalid event type passed to listener " . static::class);
}
Logger::info("Database connection event", [get_class($event), $event->connectionName]); Logger::info("Database connection event", [get_class($event), $event->connectionName]);

View File

@@ -6,6 +6,7 @@ namespace Siteworxpro\App\Services\ServiceProviders;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Siteworxpro\App\Log\Logger; use Siteworxpro\App\Log\Logger;
use Siteworxpro\App\Services\Facades\Config;
/** /**
* Class LoggerServiceProvider * Class LoggerServiceProvider
@@ -17,7 +18,7 @@ class LoggerServiceProvider extends ServiceProvider
public function register(): void public function register(): void
{ {
$this->app->singleton(Logger::class, function () { $this->app->singleton(Logger::class, function () {
return new Logger(); return new Logger(Config::get('app.log_level'));
}); });
} }
} }

View File

@@ -11,7 +11,10 @@ class HandlesMessageTest extends Unit
{ {
public function testGetsClass(): void public function testGetsClass(): void
{ {
$reflection = new \ReflectionClass(TestClass::class); $class = new #[HandlesMessage('Siteworxpro\Tests\Attributes\TestClass')] class {
};
$reflection = new \ReflectionClass($class);
$attributes = $reflection->getAttributes(HandlesMessage::class); $attributes = $reflection->getAttributes(HandlesMessage::class);
$this->assertCount(1, $attributes); $this->assertCount(1, $attributes);
@@ -20,8 +23,3 @@ class HandlesMessageTest extends Unit
$this->assertEquals('Siteworxpro\Tests\Attributes\TestClass', $instance->getMessageClass()); $this->assertEquals('Siteworxpro\Tests\Attributes\TestClass', $instance->getMessageClass());
} }
} }
#[HandlesMessage('Siteworxpro\Tests\Attributes\TestClass')]
class TestClass // @codingStandardsIgnoreLine
{
}

View File

@@ -22,4 +22,19 @@ class IndexControllerTest extends AbstractController
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"status_code":200,"message":"Server is running"}', (string)$response->getBody()); $this->assertEquals('{"status_code":200,"message":"Server is running"}', (string)$response->getBody());
} }
/**
* @throws \JsonException
*/
public function testPost(): void
{
$this->assertTrue(true);
$controller = new IndexController();
$response = $controller->post($this->getMockRequest());
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"status_code":200,"message":"Server is running"}', (string)$response->getBody());
}
} }

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Events\Listeners;
use Illuminate\Database\Events\ConnectionEstablished;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LogLevel;
use Siteworxpro\App\Events\Listeners\Database\Connected;
use Siteworxpro\App\Log\Logger;
use Siteworxpro\Tests\Unit;
class ConnectedTest extends Unit
{
/**
* @throws ContainerExceptionInterface
* @throws \ReflectionException
* @throws NotFoundExceptionInterface
*/
protected function setUp(): void
{
parent::setUp();
$inputBuffer = fopen('php://memory', 'r+');
$logger = new Logger(LogLevel::DEBUG, $inputBuffer);
\Siteworxpro\App\Services\Facades\Logger::getFacadeContainer()->bind(Logger::class, fn() => $logger);
}
public function testHandlesEvent()
{
$this->expectNotToPerformAssertions();
$connectedEvent = $this->createMock(ConnectionEstablished::class);
$listener = new Connected();
$listener->__invoke($connectedEvent);
}
public function testThrowsException()
{
$this->expectException(\TypeError::class);
$listener = new Connected();
$listener->__invoke(new \stdClass());
}
}

View File

@@ -11,7 +11,7 @@ use Siteworxpro\App\Http\Middleware\CorsMiddleware;
use Siteworxpro\App\Services\Facades\Config; use Siteworxpro\App\Services\Facades\Config;
use Siteworxpro\Tests\Unit; use Siteworxpro\Tests\Unit;
class CorsMiddlewareTest extends Unit class CorsMiddlewareTest extends Middleware
{ {
public function testAllowsConfiguredOrigin(): void public function testAllowsConfiguredOrigin(): void
{ {
@@ -80,22 +80,4 @@ class CorsMiddlewareTest extends Unit
$this->assertEquals('true', $response->getHeaderLine('Access-Control-Allow-Credentials')); $this->assertEquals('true', $response->getHeaderLine('Access-Control-Allow-Credentials'));
} }
private function mockHandler(Response $response): RequestHandlerInterface
{
return new class ($response) implements RequestHandlerInterface {
private Response $response;
public function __construct(Response $response)
{
$this->response = $response;
}
public function handle(
\Psr\Http\Message\ServerRequestInterface $request
): \Psr\Http\Message\ResponseInterface {
return $this->response;
}
};
}
} }

View File

@@ -0,0 +1,230 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Http\Middleware;
use DateTimeImmutable;
use Lcobucci\JWT\JwtFacade;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Token\Builder;
use League\Route\Dispatcher;
use Nyholm\Psr7\Response;
use Nyholm\Psr7\ServerRequest;
use Siteworxpro\App\Attributes\Guards\Jwt;
use Siteworxpro\App\Http\Middleware\JwtMiddleware;
use Siteworxpro\App\Services\Facades\Config;
use Siteworxpro\HttpStatus\CodesEnum;
class JwtMiddlewareTest extends Middleware
{
private const string TEST_SIGNING_KEY = 'test_signing_key_123456444478901234';
public function getClass(): object
{
return new class {
public function getCallable(): array
{
return [$this, 'index'];
}
#[Jwt]
public function index()
{
// Dummy method for testing
}
};
}
protected function setUp(): void
{
parent::setUp();
Config::set('jwt.signing_key', self::TEST_SIGNING_KEY);
}
/**
* @throws \JsonException
*/
public function testIgnoresNoJwtAttribute()
{
$class = new class {
public function getCallable(): array
{
return [ $this, 'index' ];
}
public function index()
{
// Dummy method for testing
}
};
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$handler
->shouldReceive('handle')
->once()
->andReturn(new Response(200));
$request = new ServerRequest('GET', '/');
$middleware = new JwtMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::OK->value, $response->getStatusCode());
}
/**
* @throws \JsonException
*/
public function testIgnoresJwtAttributeButNoToken()
{
$class = $this->getClass();
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$request = new ServerRequest('GET', '/');
$middleware = new JwtMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::UNAUTHORIZED->value, $response->getStatusCode());
}
/**
* @throws \JsonException
*/
public function testInvalidToken()
{
$class = $this->getClass();
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$request = new ServerRequest('GET', '/');
$request = $request->withHeader('Authorization', 'Bearer ' . 'invalid_token_string');
$middleware = new JwtMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::UNAUTHORIZED->value, $response->getStatusCode());
$this->assertStringContainsString(
'Unauthorized: Invalid token',
$response->getBody()->getContents()
);
}
/**
* @throws \JsonException
*/
public function testJwtAttributeWithTokenButWrongAud()
{
$class = $this->getClass();
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$request = new ServerRequest('GET', '/');
$request = $request->withHeader('Authorization', 'Bearer ' . $this->getJwt());
$middleware = new JwtMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::UNAUTHORIZED->value, $response->getStatusCode());
$this->assertStringContainsString(
'The token is not allowed to be used by this audience',
$response->getBody()->getContents()
);
}
/**
* @throws \JsonException
*/
public function testJwtAttributeWithTokenButWrongIss()
{
Config::set('jwt.audience', 'https://client-app.io');
$class = $this->getClass();
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$request = new ServerRequest('GET', '/');
$request = $request->withHeader('Authorization', 'Bearer ' . $this->getJwt());
$middleware = new JwtMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::UNAUTHORIZED->value, $response->getStatusCode());
$this->assertStringContainsString(
'The token was not issued by the given issuers',
$response->getBody()->getContents()
);
}
/**
* @throws \JsonException
*/
public function testJwtAttributeWithTokenWithDiffIssuer()
{
Config::set('jwt.audience', 'https://client-app.io');
Config::set('jwt.issuer', 'https://different-issuer.io');
$class = $this->getClass();
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$request = new ServerRequest('GET', '/');
$request = $request->withHeader('Authorization', 'Bearer ' . $this->getJwt());
$middleware = new JwtMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::UNAUTHORIZED->value, $response->getStatusCode());
$this->assertStringContainsString(
'The token was not issued by the given issuers',
$response->getBody()->getContents()
);
}
public function testJwtAttributeWithToken()
{
Config::set('jwt.audience', 'https://client-app.io');
Config::set('jwt.issuer', 'https://api.my-awesome-app.io');
$class = $this->getClass();
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$handler
->shouldReceive('handle')
->once()
->andReturn(new Response(200));
$request = new ServerRequest('GET', '/');
$request = $request->withHeader('Authorization', 'Bearer ' . $this->getJwt());
$middleware = new JwtMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::OK->value, $response->getStatusCode());
}
private function getJwt(): string
{
$key = InMemory::plainText(self::TEST_SIGNING_KEY);
$signer = new Sha256();
$token = new JwtFacade()->issue(
$signer,
$key,
static fn (
Builder $builder,
DateTimeImmutable $issuedAt
): Builder => $builder
->issuedBy('https://api.my-awesome-app.io')
->permittedFor('https://client-app.io')
->expiresAt($issuedAt->modify('+10 minutes'))
);
return $token->toString();
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Http\Middleware;
use Nyholm\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Siteworxpro\Tests\Unit;
abstract class Middleware extends Unit
{
protected function mockHandler(Response $response): RequestHandlerInterface
{
return new class ($response) implements RequestHandlerInterface {
private Response $response;
public function __construct(Response $response)
{
$this->response = $response;
}
public function handle(
ServerRequestInterface $request
): ResponseInterface {
return $this->response;
}
};
}
}

View File

@@ -0,0 +1,111 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Http\Middleware;
use League\Route\Dispatcher;
use Nyholm\Psr7\Response;
use Nyholm\Psr7\ServerRequest;
use Siteworxpro\App\Attributes\Guards\Scope;
use Siteworxpro\App\Http\Middleware\ScopeMiddleware;
use Siteworxpro\HttpStatus\CodesEnum;
class ScopeMiddlewareTest extends Middleware
{
/**
* @throws \ReflectionException
* @throws \JsonException
*/
public function testHandlesNoScopes()
{
$class = new class {
public function getCallable(): array
{
return [ $this, 'index' ];
}
public function index()
{
// Dummy method for testing
}
};
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$handler
->shouldReceive('handle')
->once()
->andReturn(new Response(200));
$request = new ServerRequest('GET', '/');
$middleware = new ScopeMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(200, $response->getStatusCode());
}
/**
* @throws \ReflectionException
* @throws \JsonException
*/
public function testAllowsWithScope()
{
$class = new class {
public function getCallable(): array
{
return [ $this, 'index' ];
}
#[Scope(['admin'])]
public function index()
{
// Dummy method for testing
}
};
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$handler
->shouldReceive('handle')
->once()
->andReturn(new Response(200));
$request = new ServerRequest('GET', '/')->withAttribute('scopes', ['admin', 'user']);
$middleware = new ScopeMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::OK->value, $response->getStatusCode());
}
/**
* @throws \ReflectionException
* @throws \JsonException
*/
public function testDisallowsWithScope()
{
$class = new class {
public function getCallable(): array
{
return [ $this, 'index' ];
}
#[Scope(['admin'])]
public function index()
{
// Dummy method for testing
}
};
$handler = \Mockery::mock(Dispatcher::class);
$handler->shouldReceive('getMiddlewareStack')
->andReturn([$class]);
$request = new ServerRequest('GET', '/');
$middleware = new ScopeMiddleware();
$response = $middleware->process($request, $handler);
$this->assertEquals(CodesEnum::FORBIDDEN->value, $response->getStatusCode());
}
}

View File

@@ -34,7 +34,7 @@ class LoggerRpcTest extends Unit
$mock = Mockery::mock(LoggerInterface::class); $mock = Mockery::mock(LoggerInterface::class);
$mock->expects('debug') $mock->expects('debug')
->with('message', ['key' => 'value']) ->with('message', ['key' => 'value'])
->once(); ->times(1);
\Siteworxpro\App\Services\Facades\Logger::getFacadeContainer() \Siteworxpro\App\Services\Facades\Logger::getFacadeContainer()
->bind(\RoadRunner\Logger\Logger::class, function () use ($mock) { ->bind(\RoadRunner\Logger\Logger::class, function () use ($mock) {
@@ -46,8 +46,6 @@ class LoggerRpcTest extends Unit
$logger->debug('message', ['key' => 'value']); $logger->debug('message', ['key' => 'value']);
$mock->shouldHaveReceived('debug'); $mock->shouldHaveReceived('debug');
Mockery::close();
} }
/** /**
@@ -76,7 +74,6 @@ class LoggerRpcTest extends Unit
$logger->notice('message', ['key' => 'value']); $logger->notice('message', ['key' => 'value']);
$mock->shouldHaveReceived('info')->times(2); $mock->shouldHaveReceived('info')->times(2);
Mockery::close();
} }
/** /**
@@ -104,7 +101,6 @@ class LoggerRpcTest extends Unit
$logger->warning('message', ['key' => 'value']); $logger->warning('message', ['key' => 'value']);
$mock->shouldHaveReceived('warning'); $mock->shouldHaveReceived('warning');
Mockery::close();
} }
/** /**
@@ -135,7 +131,6 @@ class LoggerRpcTest extends Unit
$logger->emergency('message', ['key' => 'value']); $logger->emergency('message', ['key' => 'value']);
$mock->shouldHaveReceived('error')->times(4); $mock->shouldHaveReceived('error')->times(4);
Mockery::close();
} }
/** /**
@@ -162,6 +157,5 @@ class LoggerRpcTest extends Unit
$logger->log('notaloglevel', 'message', ['key' => 'value']); $logger->log('notaloglevel', 'message', ['key' => 'value']);
$mock->shouldHaveReceived('log')->times(1); $mock->shouldHaveReceived('log')->times(1);
Mockery::close();
} }
} }

View File

@@ -4,12 +4,18 @@ declare(strict_types=1);
namespace Siteworxpro\Tests\Log; namespace Siteworxpro\Tests\Log;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Siteworxpro\App\Log\Logger; use Siteworxpro\App\Log\Logger;
use Siteworxpro\Tests\Unit; use Siteworxpro\Tests\Unit;
class LoggerTest extends Unit class LoggerTest extends Unit
{ {
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function getLoggerWithBuffer(string $logLevel): array private function getLoggerWithBuffer(string $logLevel): array
{ {
$inputBuffer = fopen('php://memory', 'r+'); $inputBuffer = fopen('php://memory', 'r+');
@@ -21,6 +27,10 @@ class LoggerTest extends Unit
return stream_get_contents($inputBuffer, -1, 0); return stream_get_contents($inputBuffer, -1, 0);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function testLogLevel(string $level): void private function testLogLevel(string $level): void
{ {
[$logger, $inputBuffer] = $this->getLoggerWithBuffer($level); [$logger, $inputBuffer] = $this->getLoggerWithBuffer($level);
@@ -33,6 +43,10 @@ class LoggerTest extends Unit
$this->assertEquals('value', $decoded['context']['key']); $this->assertEquals('value', $decoded['context']['key']);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function testLogLevelEmpty(string $configLevel, string $logLevel): void private function testLogLevelEmpty(string $configLevel, string $logLevel): void
{ {
[$logger, $inputBuffer] = $this->getLoggerWithBuffer($configLevel); [$logger, $inputBuffer] = $this->getLoggerWithBuffer($configLevel);
@@ -42,57 +56,101 @@ class LoggerTest extends Unit
$this->assertEmpty($output); $this->assertEmpty($output);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsDebugMessageWhenLevelIsDebug(): void public function testLogsDebugMessageWhenLevelIsDebug(): void
{ {
$this->testLogLevel(LogLevel::DEBUG); $this->testLogLevel(LogLevel::DEBUG);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsInfoMessageWhenLevelIsInfo(): void public function testLogsInfoMessageWhenLevelIsInfo(): void
{ {
$this->testLogLevel(LogLevel::INFO); $this->testLogLevel(LogLevel::INFO);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsWarningMessageWhenLevelIsWarning(): void public function testLogsWarningMessageWhenLevelIsWarning(): void
{ {
$this->testLogLevel(LogLevel::WARNING); $this->testLogLevel(LogLevel::WARNING);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsErrorMessageWhenLevelIsError(): void public function testLogsErrorMessageWhenLevelIsError(): void
{ {
$this->testLogLevel(LogLevel::ERROR); $this->testLogLevel(LogLevel::ERROR);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsCriticalMessageWhenLevelIsCritical(): void public function testLogsCriticalMessageWhenLevelIsCritical(): void
{ {
$this->testLogLevel(LogLevel::CRITICAL); $this->testLogLevel(LogLevel::CRITICAL);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsAlertMessageWhenLevelIsAlert(): void public function testLogsAlertMessageWhenLevelIsAlert(): void
{ {
$this->testLogLevel(LogLevel::ALERT); $this->testLogLevel(LogLevel::ALERT);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsEmergencyMessageWhenLevelIsEmergency(): void public function testLogsEmergencyMessageWhenLevelIsEmergency(): void
{ {
$this->testLogLevel(LogLevel::EMERGENCY); $this->testLogLevel(LogLevel::EMERGENCY);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsNoticeMessageWhenLevelIsNotice(): void public function testLogsNoticeMessageWhenLevelIsNotice(): void
{ {
$this->testLogLevel(LogLevel::NOTICE); $this->testLogLevel(LogLevel::NOTICE);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testDoesNotLogWhenMinimumLevelIsInfo(): void public function testDoesNotLogWhenMinimumLevelIsInfo(): void
{ {
$this->testLogLevelEmpty(LogLevel::INFO, LogLevel::DEBUG); $this->testLogLevelEmpty(LogLevel::INFO, LogLevel::DEBUG);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testDoesNotLogWhenMinimumLevelIsWarning(): void public function testDoesNotLogWhenMinimumLevelIsWarning(): void
{ {
$this->testLogLevelEmpty(LogLevel::WARNING, LogLevel::INFO); $this->testLogLevelEmpty(LogLevel::WARNING, LogLevel::INFO);
$this->testLogLevelEmpty(LogLevel::WARNING, LogLevel::DEBUG); $this->testLogLevelEmpty(LogLevel::WARNING, LogLevel::DEBUG);
} }
/**
* @throws NotFoundExceptionInterface
* @throws ContainerExceptionInterface
*/
public function testDoesNotLogWhenMinimumLevelIsError(): void public function testDoesNotLogWhenMinimumLevelIsError(): void
{ {
$this->testLogLevelEmpty(LogLevel::ERROR, LogLevel::DEBUG); $this->testLogLevelEmpty(LogLevel::ERROR, LogLevel::DEBUG);
@@ -100,12 +158,20 @@ class LoggerTest extends Unit
$this->testLogLevelEmpty(LogLevel::ERROR, LogLevel::WARNING); $this->testLogLevelEmpty(LogLevel::ERROR, LogLevel::WARNING);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testDoesNotLogWhenMinimumLevelIsNotice(): void public function testDoesNotLogWhenMinimumLevelIsNotice(): void
{ {
$this->testLogLevelEmpty(LogLevel::NOTICE, LogLevel::DEBUG); $this->testLogLevelEmpty(LogLevel::NOTICE, LogLevel::DEBUG);
$this->testLogLevelEmpty(LogLevel::NOTICE, LogLevel::INFO); $this->testLogLevelEmpty(LogLevel::NOTICE, LogLevel::INFO);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsMessageWithEmptyContext(): void public function testLogsMessageWithEmptyContext(): void
{ {
[$logger, $buffer] = $this->getLoggerWithBuffer(LogLevel::INFO); [$logger, $buffer] = $this->getLoggerWithBuffer(LogLevel::INFO);
@@ -118,6 +184,10 @@ class LoggerTest extends Unit
$this->assertEquals('Message without context', $decoded['message']); $this->assertEquals('Message without context', $decoded['message']);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsMessageWithComplexContext(): void public function testLogsMessageWithComplexContext(): void
{ {
[$logger, $buffer] = $this->getLoggerWithBuffer(LogLevel::INFO); [$logger, $buffer] = $this->getLoggerWithBuffer(LogLevel::INFO);
@@ -135,6 +205,10 @@ class LoggerTest extends Unit
$this->assertEquals('value', $decoded['context']['nested']['key']); $this->assertEquals('value', $decoded['context']['nested']['key']);
} }
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function testLogsStringableMessage(): void public function testLogsStringableMessage(): void
{ {
[$logger, $buffer] = $this->getLoggerWithBuffer(LogLevel::INFO); [$logger, $buffer] = $this->getLoggerWithBuffer(LogLevel::INFO);

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Siteworxpro\Tests; namespace Siteworxpro\Tests;
use Illuminate\Container\Container; use Illuminate\Container\Container;
use Mockery;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Siteworx\Config\Config as SWConfig; use Siteworx\Config\Config as SWConfig;
use Siteworxpro\App\Services\Facade; use Siteworxpro\App\Services\Facade;
@@ -29,5 +30,6 @@ abstract class Unit extends TestCase
{ {
Config::clearResolvedInstances(); Config::clearResolvedInstances();
Facade::setFacadeContainer(null); Facade::setFacadeContainer(null);
Mockery::close();
} }
} }