From d09d2c4d08aa0551807eba2c68c089d9c8066be1 Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 00:35:05 +0100 Subject: [PATCH 01/17] migrate test to pest part one --- .github/workflows/codestyle-and-unittest.yml | 7 +- .phpstorm.meta.php | 4 + composer.json | 18 +- composer.lock | 2235 ++++++++++++++--- config/autoload/dependencies.global.php | 1 + config/autoload/dependencies.testing.php | 25 +- config/autoload/mail.testing.php | 8 - config/autoload/migrations.testing.php | 1 - config/autoload/project.testing.php | 21 - config/autoload/token.global.php | 20 + config/autoload/token.testing.php | 4 +- config/config.php | 1 + docker/php/php-ini-overrides.ini | 2 +- phpstan.neon | 3 + .../Account/Identity/src/ConfigProvider.php | 65 +- .../src/Domain/Message/IdentityLogMessage.php | 1 + .../src/Handler/AccountRegisterHandler.php | 4 +- .../Account/AccountRegisterService.php | 2 +- .../AccountRegisterServiceInterface.php | 10 + .../EmailInputValidatorMiddleware.php | 2 +- src/Shared/src/Handler/PingHandler.php | 6 +- .../Account/AccountActivationHandlerTest.php | 119 - .../Account/AccountRegisterHandlerTest.php | 104 - .../Account/AuthenticationHandlerTest.php | 181 -- .../InvalidEMailAddressProviderTrait.php | 54 - .../Identity/AccountActivationTest.php | 96 + .../Account/Identity/AuthenticationTest.php | 188 ++ .../Factory/AccountAccessAuthFactory.php | 33 + .../Factory/AccountActivationFactory.php | 33 + .../Identity/Factory/AccountFactory.php | 41 + .../App/Account/Identity/RegisterTest.php | 86 + .../App/Account/Identity/TokenRefreshTest.php | 119 + .../Factory/RequestPipingFactory.php | 47 + tests/Integration/JsonFactory.php | 13 + .../Mock/NullLogger.php | 2 +- .../Mock/NullLoggerFactory.php | 2 +- .../Mock/NullMailer.php | 2 +- .../Mock/NullMailerFactory.php | 2 +- tests/Integration/PingTest.php | 23 + tests/Pest.php | 137 + tests/TestIntegrationCase.php | 107 + .../FunctionalTest/AbstractFunctional.php | 0 .../Root/Account/AccessTokenHandlerTest.php | 0 .../AccountPasswordForgottenHandlerTest.php | 0 .../Account/AccountPasswordHandlerTest.php | 0 .../FunctionalTest/Root/PingHandlerTest.php | 0 .../ListOwnWorkspacesHandlerTest.php | 0 .../Workspace/WorkspaceCreateHandlerTest.php | 0 .../FunctionalTest/bootstrap.php | 0 ...on20990921210156_InsertAccountTestData.php | 0 ...20990921210157_InsertWorkspaceTestData.php | 0 .../AppTest/Handler/AbstractTestHandler.php | 0 .../AppTest/Handler/PingHandlerTest.php | 0 .../AccountAccessAuthHydratorTest.php | 0 .../AppTest/Hydrator/AccountHydratorTest.php | 0 .../Middleware/AbstractTestMiddleware.php | 0 ...AccountAccessAuthPersistMiddlewareTest.php | 0 .../AccountAuthenticationMiddlewareTest.php | 2 +- ...AuthenticationConditionsMiddlewareTest.php | 0 ...AuthenticationValidationMiddlewareTest.php | 0 .../ClientIdentificationMiddlewareTest.php | 0 .../GenerateAccessTokenMiddlewareTest.php | 0 .../GenerateRefreshTokenMiddlewareTest.php | 0 .../AccountAccessAuthRepositoryTest.php | 0 .../Repository/AccountRepositoryTest.php | 0 .../Service/AccessTokenServiceTest.php | 0 .../Service/AuthenticationServiceTest.php | 0 .../Service/RefreshTokenServiceTest.php | 0 .../Table/AccountAccessAuthTableTest.php | 0 .../AppTest/Table/AccountTableTest.php | 0 .../CoreTest/Factory/DatabaseFactoryTest.php | 0 .../CoreTest/Factory/QueryFactoryTest.php | 0 .../UnitTest/JsonRequestHelper.php | 0 .../UnitTest/Mock/Constants/Account.php | 0 .../Mock/Constants/AccountAccessAuth.php | 0 .../UnitTest/Mock/Constants/Token.php | 0 .../UnitTest/Mock/Database/MockDelete.php | 0 .../Mock/Database/MockDeleteFailed.php | 0 .../UnitTest/Mock/Database/MockInsert.php | 0 .../Mock/Database/MockInsertFailed.php | 0 .../UnitTest/Mock/Database/MockPDO.php | 0 .../UnitTest/Mock/Database/MockQuery.php | 0 .../Mock/Database/MockQueryFailed.php | 0 .../UnitTest/Mock/Database/MockSelect.php | 0 .../Mock/Database/MockSelectFailed.php | 0 .../UnitTest/Mock/Database/MockUpdate.php | 0 .../Mock/Database/MockUpdateFailed.php | 0 .../UnitTest/Mock/Entity/MockAccount.php | 0 ...AuthenticationMiddlewareRequestHandler.php | 0 .../UnitTest/Mock/MockContainer.php | 0 .../UnitTest/Mock/MockRequestHandler.php | 0 .../UnitTest/Mock/MockResponse.php | 0 .../UnitTest/Mock/MockServerRequest.php | 0 .../MockAccountAccessAuthRepository.php | 0 .../Mock/Repository/MockAccountRepository.php | 0 ...ntAuthenticationMiddlewareInvalidToken.php | 0 .../Mock/Service/MockAccessTokenService.php | 0 .../MockAccessTokenServiceWithoutDuration.php | 0 .../Service/MockAuthenticationService.php | 0 .../MockClientIdentificationService.php | 0 .../Mock/Service/MockRefreshTokenService.php | 0 .../Mock/Table/MockAccountAccessAuthTable.php | 0 .../MockAccountAccessAuthTableFailed.php | 0 .../UnitTest/Mock/Table/MockAccountTable.php | 0 ...ntAuthenticationMiddlewareInvalidToken.php | 0 .../Mock/Table/MockAccountTableFailed.php | 0 .../Validator/MockAuthenticationValidator.php | 0 .../MockAuthenticationValidatorFailed.php | 0 108 files changed, 2866 insertions(+), 965 deletions(-) delete mode 100644 config/autoload/mail.testing.php delete mode 100644 config/autoload/project.testing.php create mode 100644 config/autoload/token.global.php create mode 100644 src/App/Account/Identity/src/Infrastructure/Service/Account/AccountRegisterServiceInterface.php delete mode 100644 tests/FunctionalTest/Root/Account/AccountActivationHandlerTest.php delete mode 100644 tests/FunctionalTest/Root/Account/AccountRegisterHandlerTest.php delete mode 100644 tests/FunctionalTest/Root/Account/AuthenticationHandlerTest.php delete mode 100644 tests/FunctionalTest/Root/Account/InvalidEMailAddressProviderTrait.php create mode 100644 tests/Integration/App/Account/Identity/AccountActivationTest.php create mode 100644 tests/Integration/App/Account/Identity/AuthenticationTest.php create mode 100644 tests/Integration/App/Account/Identity/Factory/AccountAccessAuthFactory.php create mode 100644 tests/Integration/App/Account/Identity/Factory/AccountActivationFactory.php create mode 100644 tests/Integration/App/Account/Identity/Factory/AccountFactory.php create mode 100644 tests/Integration/App/Account/Identity/RegisterTest.php create mode 100644 tests/Integration/App/Account/Identity/TokenRefreshTest.php create mode 100644 tests/Integration/Factory/RequestPipingFactory.php create mode 100644 tests/Integration/JsonFactory.php rename tests/{FunctionalTest => Integration}/Mock/NullLogger.php (97%) rename tests/{FunctionalTest => Integration}/Mock/NullLoggerFactory.php (88%) rename tests/{FunctionalTest => Integration}/Mock/NullMailer.php (90%) rename tests/{FunctionalTest => Integration}/Mock/NullMailerFactory.php (89%) create mode 100644 tests/Integration/PingTest.php create mode 100644 tests/Pest.php create mode 100644 tests/TestIntegrationCase.php rename {tests => tests_backup}/FunctionalTest/AbstractFunctional.php (100%) rename {tests => tests_backup}/FunctionalTest/Root/Account/AccessTokenHandlerTest.php (100%) rename {tests => tests_backup}/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php (100%) rename {tests => tests_backup}/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php (100%) rename {tests => tests_backup}/FunctionalTest/Root/PingHandlerTest.php (100%) rename {tests => tests_backup}/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php (100%) rename {tests => tests_backup}/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php (100%) rename {tests => tests_backup}/FunctionalTest/bootstrap.php (100%) rename {tests => tests_backup}/FunctionalTest/database/migrations/Version20990921210156_InsertAccountTestData.php (100%) rename {tests => tests_backup}/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Handler/AbstractTestHandler.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Handler/PingHandlerTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Hydrator/AccountHydratorTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php (99%) rename {tests => tests_backup}/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Repository/AccountRepositoryTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Service/AccessTokenServiceTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Service/AuthenticationServiceTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Service/RefreshTokenServiceTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php (100%) rename {tests => tests_backup}/UnitTest/AppTest/Table/AccountTableTest.php (100%) rename {tests => tests_backup}/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php (100%) rename {tests => tests_backup}/UnitTest/CoreTest/Factory/QueryFactoryTest.php (100%) rename {tests => tests_backup}/UnitTest/JsonRequestHelper.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Constants/Account.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Constants/AccountAccessAuth.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Constants/Token.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockDelete.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockDeleteFailed.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockInsert.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockInsertFailed.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockPDO.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockQuery.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockQueryFailed.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockSelect.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockSelectFailed.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockUpdate.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Database/MockUpdateFailed.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Entity/MockAccount.php (100%) rename {tests => tests_backup}/UnitTest/Mock/MockAccountAuthenticationMiddlewareRequestHandler.php (100%) rename {tests => tests_backup}/UnitTest/Mock/MockContainer.php (100%) rename {tests => tests_backup}/UnitTest/Mock/MockRequestHandler.php (100%) rename {tests => tests_backup}/UnitTest/Mock/MockResponse.php (100%) rename {tests => tests_backup}/UnitTest/Mock/MockServerRequest.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Repository/MockAccountRepository.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Repository/MockAccountRepositoryAccountAuthenticationMiddlewareInvalidToken.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Service/MockAccessTokenService.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Service/MockAuthenticationService.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Service/MockClientIdentificationService.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Service/MockRefreshTokenService.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Table/MockAccountAccessAuthTable.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Table/MockAccountTable.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Table/MockAccountTableFailed.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Validator/MockAuthenticationValidator.php (100%) rename {tests => tests_backup}/UnitTest/Mock/Validator/MockAuthenticationValidatorFailed.php (100%) diff --git a/.github/workflows/codestyle-and-unittest.yml b/.github/workflows/codestyle-and-unittest.yml index 7ab5f60a..921472f3 100644 --- a/.github/workflows/codestyle-and-unittest.yml +++ b/.github/workflows/codestyle-and-unittest.yml @@ -69,11 +69,8 @@ jobs: - name: Setup PHP and Composer uses: ./.github/actions/setup-php-composer - - name: Run PHP Unit Test - run: composer run-script unittest - - - name: Run PHP Functional Test - run: composer run-script functionaltest + - name: Run PHP Integration Test + run: composer run-script pest - name: Notify Failure if: failure() diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index 4563bf51..bb4d71b3 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -6,4 +6,8 @@ \Psr\Http\Message\ServerRequestInterface::getAttribute(0), map(['' => '@',]), ); + override( + \Psr\Container\ContainerInterface::get(0), + map(['' => '@',]), + ); } diff --git a/composer.json b/composer.json index 2729db07..ccf6107f 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "allow-plugins": { "composer/package-versions-deprecated": true, "dealerdirect/phpcodesniffer-composer-installer": true, - "laminas/laminas-component-installer": true + "laminas/laminas-component-installer": true, + "pestphp/pest-plugin": true }, "platform": { "php": "8.4.16" @@ -57,21 +58,24 @@ "mezzio/mezzio-helpers": "^5.7", "monolog/monolog": "^3.9.0", "ramsey/uuid": "^4.7", - "symfony/mailer": "^8", + "symfony/mailer": "^6.4", "zircote/swagger-php": "^6", "jetbrains/phpstorm-attributes": "^1.0" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.2", "doctrine/migrations": "^3.6", + "fakerphp/faker": "^1.24", "filp/whoops": "^2.7.1", "helmich/phpunit-json-assert": "^3.5", "helmich/phpunit-psr7-assert": "^4.4", + "mockery/mockery": "^1.6", "overtrue/phplint": "^9.0", + "pestphp/pest": "^v3.7", "phpstan/phpstan": "^2.1.33", "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpunit/php-code-coverage": "^10.0", - "phpunit/phpunit": "^10.0", + "phpunit/php-code-coverage": "^11.0.0", + "phpunit/phpunit": "^11.5.0", "roave/security-advisories": "dev-master", "slevomat/coding-standard": "^8.15", "squizlabs/php_codesniffer": "^4.0" @@ -90,7 +94,8 @@ "autoload-dev": { "psr-4": { "FunctionalTest\\": "tests/FunctionalTest/", - "UnitTest\\": "tests/UnitTest/" + "UnitTest\\": "tests/UnitTest/", + "Tests\\": "tests/" } }, "scripts": { @@ -113,11 +118,12 @@ "phpcs": "phpcs --standard=phpcs.xml -s -p", "phplint": "vendor/bin/phplint", "phpstan": "vendor/bin/phpstan analyse -c phpstan.neon", + "pest": "vendor/bin/pest", "post-create-project-cmd": [ "@development-enable" ], "test": [ - "@functionaltest" + "@pest" ], "unittest": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --colors=always --display-phpunit-deprecations --configuration phpunit_unittest.xml" } diff --git a/composer.lock b/composer.lock index 346de3ae..78eda2cd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1a6899dfb7acc2c2a218b4d63c4136ec", + "content-hash": "b5d9ef0b441a66ec0eb67bdb20fba3b6", "packages": [ { "name": "brick/math", - "version": "0.14.1", + "version": "0.14.2", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" + "reference": "55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", - "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", + "url": "https://api.github.com/repos/brick/math/zipball/55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2", + "reference": "55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2", "shasum": "" }, "require": { @@ -56,7 +56,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.1" + "source": "https://github.com/brick/math/tree/0.14.2" }, "funding": [ { @@ -64,7 +64,7 @@ "type": "github" } ], - "time": "2025-11-24T14:40:29+00:00" + "time": "2026-01-30T14:03:11+00:00" }, { "name": "brick/varexporter", @@ -2263,16 +2263,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.1", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374" + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/16dbf9937da8d4528ceb2145c9c7c0bd29e26374", - "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", "shasum": "" }, "require": { @@ -2304,9 +2304,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.1" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" }, - "time": "2026-01-12T11:33:04+00:00" + "time": "2026-01-25T14:56:51+00:00" }, { "name": "psr/container", @@ -2895,16 +2895,16 @@ }, { "name": "symfony/console", - "version": "v7.4.3", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6" + "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6", - "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6", + "url": "https://api.github.com/repos/symfony/console/zipball/41e38717ac1dd7a46b6bda7d6a82af2d98a78894", + "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894", "shasum": "" }, "require": { @@ -2969,7 +2969,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.3" + "source": "https://github.com/symfony/console/tree/v7.4.4" }, "funding": [ { @@ -2989,7 +2989,7 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:50:43+00:00" + "time": "2026-01-13T11:36:38+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3060,16 +3060,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v7.4.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d" + "reference": "dc2c0eba1af673e736bb851d747d266108aea746" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9dddcddff1ef974ad87b3708e4b442dc38b2261d", - "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dc2c0eba1af673e736bb851d747d266108aea746", + "reference": "dc2c0eba1af673e736bb851d747d266108aea746", "shasum": "" }, "require": { @@ -3121,7 +3121,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.4" }, "funding": [ { @@ -3141,7 +3141,7 @@ "type": "tidelift" } ], - "time": "2025-10-28T09:38:46+00:00" + "time": "2026-01-05T11:45:34+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -3221,16 +3221,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.3", + "version": "v7.4.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06" + "reference": "ad4daa7c38668dcb031e63bc99ea9bd42196a2cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06", + "url": "https://api.github.com/repos/symfony/finder/zipball/ad4daa7c38668dcb031e63bc99ea9bd42196a2cb", + "reference": "ad4daa7c38668dcb031e63bc99ea9bd42196a2cb", "shasum": "" }, "require": { @@ -3265,7 +3265,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.3" + "source": "https://github.com/symfony/finder/tree/v7.4.5" }, "funding": [ { @@ -3285,39 +3285,43 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:50:43+00:00" + "time": "2026-01-26T15:07:59+00:00" }, { "name": "symfony/mailer", - "version": "v8.0.3", + "version": "v6.4.31", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "02e033db6e00a42c66b8b8992e4e565ea7464a28" + "reference": "8835f93333474780fda1b987cae37e33c3e026ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/02e033db6e00a42c66b8b8992e4e565ea7464a28", - "reference": "02e033db6e00a42c66b8b8992e4e565ea7464a28", + "url": "https://api.github.com/repos/symfony/mailer/zipball/8835f93333474780fda1b987cae37e33c3e026ca", + "reference": "8835f93333474780fda1b987cae37e33c3e026ca", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3|^4", - "php": ">=8.4", + "php": ">=8.1", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^7.4|^8.0", - "symfony/mime": "^7.4|^8.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/http-client-contracts": "<2.5" + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" }, "require-dev": { - "symfony/console": "^7.4|^8.0", - "symfony/http-client": "^7.4|^8.0", - "symfony/messenger": "^7.4|^8.0", - "symfony/twig-bridge": "^7.4|^8.0" + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.2|^7.0", + "symfony/twig-bridge": "^6.2|^7.0" }, "type": "library", "autoload": { @@ -3345,7 +3349,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v8.0.3" + "source": "https://github.com/symfony/mailer/tree/v6.4.31" }, "funding": [ { @@ -3365,41 +3369,44 @@ "type": "tidelift" } ], - "time": "2025-12-16T08:10:18+00:00" + "time": "2025-12-12T07:33:25+00:00" }, { "name": "symfony/mime", - "version": "v8.0.0", + "version": "v7.4.5", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40" + "reference": "b18c7e6e9eee1e19958138df10412f3c4c316148" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40", - "reference": "7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40", + "url": "https://api.github.com/repos/symfony/mime/zipball/b18c7e6e9eee1e19958138df10412f3c4c316148", + "reference": "b18c7e6e9eee1e19958138df10412f3c4c316148", "shasum": "" }, "require": { - "php": ">=8.4", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0" + "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/process": "^7.4|^8.0", - "symfony/property-access": "^7.4|^8.0", - "symfony/property-info": "^7.4|^8.0", - "symfony/serializer": "^7.4|^8.0" + "phpdocumentor/reflection-docblock": "^5.2", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4.3|^7.0.3|^8.0" }, "type": "library", "autoload": { @@ -3431,7 +3438,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v8.0.0" + "source": "https://github.com/symfony/mime/tree/v7.4.5" }, "funding": [ { @@ -3451,7 +3458,7 @@ "type": "tidelift" } ], - "time": "2025-11-16T10:17:21+00:00" + "time": "2026-01-27T08:59:58+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3877,16 +3884,16 @@ }, { "name": "symfony/process", - "version": "v6.4.31", + "version": "v6.4.33", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "8541b7308fca001320e90bca8a73a28aa5604a6e" + "reference": "c46e854e79b52d07666e43924a20cb6dc546644e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/8541b7308fca001320e90bca8a73a28aa5604a6e", - "reference": "8541b7308fca001320e90bca8a73a28aa5604a6e", + "url": "https://api.github.com/repos/symfony/process/zipball/c46e854e79b52d07666e43924a20cb6dc546644e", + "reference": "c46e854e79b52d07666e43924a20cb6dc546644e", "shasum": "" }, "require": { @@ -3918,7 +3925,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.31" + "source": "https://github.com/symfony/process/tree/v6.4.33" }, "funding": [ { @@ -3938,7 +3945,7 @@ "type": "tidelift" } ], - "time": "2025-12-15T19:26:35+00:00" + "time": "2026-01-23T16:02:12+00:00" }, { "name": "symfony/service-contracts", @@ -4029,16 +4036,16 @@ }, { "name": "symfony/string", - "version": "v8.0.1", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc" + "reference": "758b372d6882506821ed666032e43020c4f57194" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ba65a969ac918ce0cc3edfac6cdde847eba231dc", - "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc", + "url": "https://api.github.com/repos/symfony/string/zipball/758b372d6882506821ed666032e43020c4f57194", + "reference": "758b372d6882506821ed666032e43020c4f57194", "shasum": "" }, "require": { @@ -4095,7 +4102,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v8.0.1" + "source": "https://github.com/symfony/string/tree/v8.0.4" }, "funding": [ { @@ -4115,20 +4122,20 @@ "type": "tidelift" } ], - "time": "2025-12-01T09:13:36+00:00" + "time": "2026-01-12T12:37:40+00:00" }, { "name": "symfony/type-info", - "version": "v8.0.1", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/type-info.git", - "reference": "bb091cec1f70383538c7d000699781813f8d1a6a" + "reference": "106a2d3bbf0d4576b2f70e6ca866fa420956ed0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/type-info/zipball/bb091cec1f70383538c7d000699781813f8d1a6a", - "reference": "bb091cec1f70383538c7d000699781813f8d1a6a", + "url": "https://api.github.com/repos/symfony/type-info/zipball/106a2d3bbf0d4576b2f70e6ca866fa420956ed0d", + "reference": "106a2d3bbf0d4576b2f70e6ca866fa420956ed0d", "shasum": "" }, "require": { @@ -4177,7 +4184,7 @@ "type" ], "support": { - "source": "https://github.com/symfony/type-info/tree/v8.0.1" + "source": "https://github.com/symfony/type-info/tree/v8.0.4" }, "funding": [ { @@ -4197,7 +4204,7 @@ "type": "tidelift" } ], - "time": "2025-12-05T14:08:45+00:00" + "time": "2026-01-09T12:15:10+00:00" }, { "name": "symfony/yaml", @@ -4394,16 +4401,16 @@ }, { "name": "zircote/swagger-php", - "version": "6.0.1", + "version": "6.0.3", "source": { "type": "git", "url": "https://github.com/zircote/swagger-php.git", - "reference": "cf332956e6603fe4c8da6223a98b7ba65e20231e" + "reference": "5d7d7371e9a9349abdc1dc83379774dcf8f72e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/cf332956e6603fe4c8da6223a98b7ba65e20231e", - "reference": "cf332956e6603fe4c8da6223a98b7ba65e20231e", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/5d7d7371e9a9349abdc1dc83379774dcf8f72e0c", + "reference": "5d7d7371e9a9349abdc1dc83379774dcf8f72e0c", "shasum": "" }, "require": { @@ -4472,7 +4479,7 @@ ], "support": { "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/6.0.1" + "source": "https://github.com/zircote/swagger-php/tree/6.0.3" }, "funding": [ { @@ -4480,10 +4487,103 @@ "type": "github" } ], - "time": "2026-01-15T19:54:20+00:00" + "time": "2026-01-22T03:43:48+00:00" } ], "packages-dev": [ + { + "name": "brianium/paratest", + "version": "v7.8.5", + "source": { + "type": "git", + "url": "https://github.com/paratestphp/paratest.git", + "reference": "9b324c8fc319cf9728b581c7a90e1c8f6361c5e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/9b324c8fc319cf9728b581c7a90e1c8f6361c5e5", + "reference": "9b324c8fc319cf9728b581c7a90e1c8f6361c5e5", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-simplexml": "*", + "fidry/cpu-core-counter": "^1.3.0", + "jean85/pretty-package-versions": "^2.1.1", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "phpunit/php-code-coverage": "^11.0.12", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-timer": "^7.0.1", + "phpunit/phpunit": "^11.5.46", + "sebastian/environment": "^7.2.1", + "symfony/console": "^6.4.22 || ^7.3.4 || ^8.0.3", + "symfony/process": "^6.4.20 || ^7.3.4 || ^8.0.3" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0.0", + "ext-pcov": "*", + "ext-posix": "*", + "phpstan/phpstan": "^2.1.33", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.11", + "phpstan/phpstan-strict-rules": "^2.0.7", + "squizlabs/php_codesniffer": "^3.13.5", + "symfony/filesystem": "^6.4.13 || ^7.3.2 || ^8.0.1" + }, + "bin": [ + "bin/paratest", + "bin/paratest_for_phpstorm" + ], + "type": "library", + "autoload": { + "psr-4": { + "ParaTest\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Scaturro", + "email": "scaturrob@gmail.com", + "role": "Developer" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com", + "role": "Developer" + } + ], + "description": "Parallel testing for PHP", + "homepage": "https://github.com/paratestphp/paratest", + "keywords": [ + "concurrent", + "parallel", + "phpunit", + "testing" + ], + "support": { + "issues": "https://github.com/paratestphp/paratest/issues", + "source": "https://github.com/paratestphp/paratest/tree/v7.8.5" + }, + "funding": [ + { + "url": "https://github.com/sponsors/Slamdunk", + "type": "github" + }, + { + "url": "https://paypal.me/filippotessarotto", + "type": "paypal" + } + ], + "time": "2026-01-08T08:02:38+00:00" + }, { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v1.2.0", @@ -4736,16 +4836,16 @@ }, { "name": "doctrine/event-manager", - "version": "2.0.1", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" + "reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/dda33921b198841ca8dbad2eaa5d4d34769d18cf", + "reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf", "shasum": "" }, "require": { @@ -4755,10 +4855,10 @@ "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.24" + "doctrine/coding-standard": "^14", + "phpdocumentor/guides-cli": "^1.4", + "phpstan/phpstan": "^2.1.32", + "phpunit/phpunit": "^10.5.58" }, "type": "library", "autoload": { @@ -4807,7 +4907,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.1" + "source": "https://github.com/doctrine/event-manager/tree/2.1.1" }, "funding": [ { @@ -4823,7 +4923,7 @@ "type": "tidelift" } ], - "time": "2024-05-22T20:47:39+00:00" + "time": "2026-01-29T07:11:08+00:00" }, { "name": "doctrine/migrations", @@ -4928,6 +5028,130 @@ ], "time": "2025-11-20T11:15:36+00:00" }, + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" + }, + "time": "2024-11-21T13:46:39+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2025-08-14T07:29:31+00:00" + }, { "name": "filp/whoops", "version": "2.18.4", @@ -4999,24 +5223,75 @@ ], "time": "2025-08-08T12:00:00+00:00" }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, { "name": "helmich/phpunit-json-assert", - "version": "v3.5.3", + "version": "v3.5.4", "source": { "type": "git", "url": "https://github.com/martin-helmich/phpunit-json-assert.git", - "reference": "82cedf4ee0a7a2e6a619fbbdab9db77c53fe3793" + "reference": "4cde4392c47906f6ca883fcf3288bbc3f28381bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/martin-helmich/phpunit-json-assert/zipball/82cedf4ee0a7a2e6a619fbbdab9db77c53fe3793", - "reference": "82cedf4ee0a7a2e6a619fbbdab9db77c53fe3793", + "url": "https://api.github.com/repos/martin-helmich/phpunit-json-assert/zipball/4cde4392c47906f6ca883fcf3288bbc3f28381bd", + "reference": "4cde4392c47906f6ca883fcf3288bbc3f28381bd", "shasum": "" }, "require": { - "justinrainbow/json-schema": "^5.0", + "justinrainbow/json-schema": "^5.0 || ^6.0", "php": "^8.1", - "softcreatr/jsonpath": "^0.8" + "softcreatr/jsonpath": "^0.8 || ^0.9 || ^1.0" }, "conflict": { "phpunit/phpunit": "<8.0 || >= 13.0" @@ -5043,7 +5318,7 @@ "description": "PHPUnit assertions for JSON documents", "support": { "issues": "https://github.com/martin-helmich/phpunit-json-assert/issues", - "source": "https://github.com/martin-helmich/phpunit-json-assert/tree/v3.5.3" + "source": "https://github.com/martin-helmich/phpunit-json-assert/tree/v3.5.4" }, "funding": [ { @@ -5055,34 +5330,34 @@ "type": "github" } ], - "time": "2025-05-19T22:04:17+00:00" + "time": "2026-01-17T14:11:33+00:00" }, { "name": "helmich/phpunit-psr7-assert", - "version": "v4.4.1", + "version": "v4.4.2", "source": { "type": "git", "url": "https://github.com/martin-helmich/phpunit-psr7-assert.git", - "reference": "f35fa69e07cc16977b52805d3abd873cc16747fd" + "reference": "3bbb8dea1087b7d76e632829d82d5869bcf4a04a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/martin-helmich/phpunit-psr7-assert/zipball/f35fa69e07cc16977b52805d3abd873cc16747fd", - "reference": "f35fa69e07cc16977b52805d3abd873cc16747fd", + "url": "https://api.github.com/repos/martin-helmich/phpunit-psr7-assert/zipball/3bbb8dea1087b7d76e632829d82d5869bcf4a04a", + "reference": "3bbb8dea1087b7d76e632829d82d5869bcf4a04a", "shasum": "" }, "require": { "helmich/phpunit-json-assert": "^3.4", - "php": "^8.0", + "php": "^8.1", "psr/http-message": "^1.1 || ^2.0" }, "conflict": { - "phpunit/phpunit": "<8.0 || >= 11.0" + "phpunit/phpunit": "<8.0 || >= 13.0" }, "require-dev": { "guzzlehttp/psr7": "^2.4", "mockery/mockery": "^1.4.1", - "phpunit/phpunit": "^8.0 || ^9.0 || ^10.0" + "phpunit/phpunit": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0" }, "type": "library", "autoload": { @@ -5103,7 +5378,7 @@ "description": "PHPUnit assertions for testing PSR7-compliant applications", "support": { "issues": "https://github.com/martin-helmich/phpunit-psr7-assert/issues", - "source": "https://github.com/martin-helmich/phpunit-psr7-assert/tree/v4.4.1" + "source": "https://github.com/martin-helmich/phpunit-psr7-assert/tree/v4.4.2" }, "funding": [ { @@ -5115,34 +5390,104 @@ "type": "github" } ], - "time": "2023-07-26T19:04:29+00:00" + "time": "2026-01-17T16:13:24+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a", + "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.1.0", + "php": "^7.4|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^7.5|^8.5|^9.6", + "rector/rector": "^2.0", + "vimeo/psalm": "^4.3 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A library to get pretty versions strings of installed dependencies", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "support": { + "issues": "https://github.com/Jean85/pretty-package-versions/issues", + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1" + }, + "time": "2025-03-19T14:43:43+00:00" }, { "name": "justinrainbow/json-schema", - "version": "5.3.1", + "version": "6.6.4", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "b5a44b6391a3bbb75c9f2b73e1ef03d6045e1e20" + "reference": "2eeb75d21cf73211335888e7f5e6fd7440723ec7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/b5a44b6391a3bbb75c9f2b73e1ef03d6045e1e20", - "reference": "b5a44b6391a3bbb75c9f2b73e1ef03d6045e1e20", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/2eeb75d21cf73211335888e7f5e6fd7440723ec7", + "reference": "2eeb75d21cf73211335888e7f5e6fd7440723ec7", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-json": "*", + "marc-mabe/php-enum": "^4.4", + "php": "^7.2 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", - "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.35" + "friendsofphp/php-cs-fixer": "3.3.0", + "json-schema/json-schema-test-suite": "^23.2", + "marc-mabe/php-enum-phpstan": "^2.0", + "phpspec/prophecy": "^1.19", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^8.5" }, "bin": [ "bin/validate-json" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.x-dev" + } + }, "autoload": { "psr-4": { "JsonSchema\\": "src/JsonSchema/" @@ -5171,56 +5516,212 @@ } ], "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", + "homepage": "https://github.com/jsonrainbow/json-schema", "keywords": [ "json", "schema" ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.1" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.6.4" }, - "time": "2025-12-12T08:56:22+00:00" + "time": "2025-12-19T15:01:32+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.13.4", + "name": "marc-mabe/php-enum", + "version": "v4.7.2", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + "url": "https://github.com/marc-mabe/php-enum.git", + "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/bb426fcdd65c60fb3638ef741e8782508fda7eef", + "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" + "ext-reflection": "*", + "php": "^7.1 | ^8.0" }, "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + "phpbench/phpbench": "^0.16.10 || ^1.0.4", + "phpstan/phpstan": "^1.3.1", + "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", + "vimeo/psalm": "^4.17.0 | ^5.26.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.2-dev", + "dev-master": "4.7-dev" + } + }, "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } + "MabeEnum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Marc Bennewitz", + "email": "dev@mabe.berlin", + "homepage": "https://mabe.berlin/", + "role": "Lead" + } + ], + "description": "Simple and fast implementation of enumerations with native PHP", + "homepage": "https://github.com/marc-mabe/php-enum", + "keywords": [ + "enum", + "enum-map", + "enum-set", + "enumeration", + "enumerator", + "enummap", + "enumset", + "map", + "set", + "type", + "type-hint", + "typehint" + ], + "support": { + "issues": "https://github.com/marc-mabe/php-enum/issues", + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.2" + }, + "time": "2025-09-14T11:18:39+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" ], "description": "Create deep copies (clones) of your objects", "keywords": [ @@ -5242,6 +5743,192 @@ ], "time": "2025-08-01T08:46:24+00:00" }, + { + "name": "nunomaduro/collision", + "version": "v8.8.3", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/1dc9e88d105699d0fee8bb18890f41b274f6b4c4", + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.18.1", + "nunomaduro/termwind": "^2.3.1", + "php": "^8.2.0", + "symfony/console": "^7.3.0" + }, + "conflict": { + "laravel/framework": "<11.44.2 || >=13.0.0", + "phpunit/phpunit": "<11.5.15 || >=13.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.8.3", + "larastan/larastan": "^3.4.2", + "laravel/framework": "^11.44.2 || ^12.18", + "laravel/pint": "^1.22.1", + "laravel/sail": "^1.43.1", + "laravel/sanctum": "^4.1.1", + "laravel/tinker": "^2.10.1", + "orchestra/testbench-core": "^9.12.0 || ^10.4", + "pestphp/pest": "^3.8.2 || ^4.0.0", + "sebastian/environment": "^7.2.1 || ^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "dev", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2025-11-20T02:55:25+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v2.3.3", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.3.6" + }, + "require-dev": { + "illuminate/console": "^11.46.1", + "laravel/pint": "^1.25.1", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", + "phpstan/phpstan": "^1.12.32", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.3.5", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2025-11-20T02:34:59+00:00" + }, { "name": "overtrue/phplint", "version": "9.6.3", @@ -5335,6 +6022,330 @@ ], "time": "2025-11-27T13:49:59+00:00" }, + { + "name": "pestphp/pest", + "version": "v3.8.5", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest.git", + "reference": "7796630eafcfd1c02660cecdde3bc6984fbf01f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest/zipball/7796630eafcfd1c02660cecdde3bc6984fbf01f4", + "reference": "7796630eafcfd1c02660cecdde3bc6984fbf01f4", + "shasum": "" + }, + "require": { + "brianium/paratest": "^7.8.5", + "nunomaduro/collision": "^8.8.3", + "nunomaduro/termwind": "^2.3.3", + "pestphp/pest-plugin": "^3.0.0", + "pestphp/pest-plugin-arch": "^3.1.1", + "pestphp/pest-plugin-mutate": "^3.0.5", + "php": "^8.2.0", + "phpunit/phpunit": "^11.5.50" + }, + "conflict": { + "filp/whoops": "<2.16.0", + "phpunit/phpunit": ">11.5.50", + "sebastian/exporter": "<6.0.0", + "webmozart/assert": "<1.11.0" + }, + "require-dev": { + "pestphp/pest-dev-tools": "^3.4.0", + "pestphp/pest-plugin-type-coverage": "^3.6.1", + "symfony/process": "^7.4.4" + }, + "bin": [ + "bin/pest" + ], + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Mutate\\Plugins\\Mutate", + "Pest\\Plugins\\Configuration", + "Pest\\Plugins\\Bail", + "Pest\\Plugins\\Cache", + "Pest\\Plugins\\Coverage", + "Pest\\Plugins\\Init", + "Pest\\Plugins\\Environment", + "Pest\\Plugins\\Help", + "Pest\\Plugins\\Memory", + "Pest\\Plugins\\Only", + "Pest\\Plugins\\Printer", + "Pest\\Plugins\\ProcessIsolation", + "Pest\\Plugins\\Profile", + "Pest\\Plugins\\Retry", + "Pest\\Plugins\\Snapshot", + "Pest\\Plugins\\Verbose", + "Pest\\Plugins\\Version", + "Pest\\Plugins\\Parallel" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php", + "src/Pest.php" + ], + "psr-4": { + "Pest\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "The elegant PHP Testing Framework.", + "keywords": [ + "framework", + "pest", + "php", + "test", + "testing", + "unit" + ], + "support": { + "issues": "https://github.com/pestphp/pest/issues", + "source": "https://github.com/pestphp/pest/tree/v3.8.5" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2026-01-28T01:33:45+00:00" + }, + { + "name": "pestphp/pest-plugin", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin.git", + "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e79b26c65bc11c41093b10150c1341cc5cdbea83", + "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0.0", + "composer-runtime-api": "^2.2.2", + "php": "^8.2" + }, + "conflict": { + "pestphp/pest": "<3.0.0" + }, + "require-dev": { + "composer/composer": "^2.7.9", + "pestphp/pest": "^3.0.0", + "pestphp/pest-dev-tools": "^3.0.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Pest\\Plugin\\Manager" + }, + "autoload": { + "psr-4": { + "Pest\\Plugin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Pest plugin manager", + "keywords": [ + "framework", + "manager", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin/tree/v3.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2024-09-08T23:21:41+00:00" + }, + { + "name": "pestphp/pest-plugin-arch", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-arch.git", + "reference": "db7bd9cb1612b223e16618d85475c6f63b9c8daa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/db7bd9cb1612b223e16618d85475c6f63b9c8daa", + "reference": "db7bd9cb1612b223e16618d85475c6f63b9c8daa", + "shasum": "" + }, + "require": { + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", + "ta-tikoma/phpunit-architecture-test": "^0.8.4" + }, + "require-dev": { + "pestphp/pest": "^3.8.1", + "pestphp/pest-dev-tools": "^3.4.0" + }, + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Arch\\Plugin" + ] + } + }, + "autoload": { + "files": [ + "src/Autoload.php" + ], + "psr-4": { + "Pest\\Arch\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Arch plugin for Pest PHP.", + "keywords": [ + "arch", + "architecture", + "framework", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2025-04-16T22:59:48+00:00" + }, + { + "name": "pestphp/pest-plugin-mutate", + "version": "v3.0.5", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-mutate.git", + "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/e10dbdc98c9e2f3890095b4fe2144f63a5717e08", + "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.2.0", + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", + "psr/simple-cache": "^3.0.0" + }, + "require-dev": { + "pestphp/pest": "^3.0.8", + "pestphp/pest-dev-tools": "^3.0.0", + "pestphp/pest-plugin-type-coverage": "^3.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Pest\\Mutate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sandro Gehri", + "email": "sandrogehri@gmail.com" + } + ], + "description": "Mutates your code to find untested cases", + "keywords": [ + "framework", + "mutate", + "mutation", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-mutate/tree/v3.0.5" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/gehrisandro", + "type": "github" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2024-09-22T07:54:40+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.4", @@ -5441,25 +6452,200 @@ "role": "Developer" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.6.6", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/5cee1d3dfc2d2aa6599834520911d246f656bcb8", + "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", + "webmozart/assert": "^1.9.1 || ^2" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.6" + }, + "time": "2025-12-22T21:13:58+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195", + "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.18|^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "description": "Library for handling version information and constraints", + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0" }, - "time": "2022-02-21T01:04:05+00:00" + "time": "2025-11-21T15:09:14+00:00" }, { "name": "phpstan/phpstan", - "version": "2.1.33", + "version": "2.1.38", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", - "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dfaf1f530e1663aa167bc3e52197adb221582629", + "reference": "dfaf1f530e1663aa167bc3e52197adb221582629", "shasum": "" }, "require": { @@ -5504,7 +6690,7 @@ "type": "github" } ], - "time": "2025-12-05T10:24:31+00:00" + "time": "2026-01-30T17:12:46+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -5555,35 +6741,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.16", + "version": "11.0.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56", + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", - "theseer/tokenizer": "^1.2.3" + "nikic/php-parser": "^5.7.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.1", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.3.1" }, "require-dev": { - "phpunit/phpunit": "^10.1" + "phpunit/phpunit": "^11.5.46" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -5592,7 +6778,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1.x-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { @@ -5621,40 +6807,52 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" } ], - "time": "2024-08-22T04:31:57+00:00" + "time": "2025-12-24T07:01:01+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.1.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -5682,7 +6880,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" }, "funding": [ { @@ -5690,28 +6888,28 @@ "type": "github" } ], - "time": "2023-08-31T06:24:48+00:00" + "time": "2024-08-27T05:02:59+00:00" }, { "name": "phpunit/php-invoker", - "version": "4.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcntl": "*" @@ -5719,7 +6917,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -5745,7 +6943,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -5753,32 +6952,32 @@ "type": "github" } ], - "time": "2023-02-03T06:56:09+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", - "version": "3.0.1", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -5805,7 +7004,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -5813,32 +7012,32 @@ "type": "github" } ], - "time": "2023-08-31T14:07:24+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", - "version": "6.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -5864,7 +7063,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -5872,20 +7072,20 @@ "type": "github" } ], - "time": "2023-02-03T06:57:52+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "10.5.60", + "version": "11.5.50", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f2e26f52f80ef77832e359205f216eeac00e320c" + "reference": "fdfc727f0fcacfeb8fcb30c7e5da173125b58be3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f2e26f52f80ef77832e359205f216eeac00e320c", - "reference": "f2e26f52f80ef77832e359205f216eeac00e320c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fdfc727f0fcacfeb8fcb30c7e5da173125b58be3", + "reference": "fdfc727f0fcacfeb8fcb30c7e5da173125b58be3", "shasum": "" }, "require": { @@ -5898,23 +7098,23 @@ "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.4", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.4", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.1", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.12", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.3", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.1", + "sebastian/exporter": "^6.3.2", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.3", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -5925,7 +7125,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.5-dev" + "dev-main": "11.5-dev" } }, "autoload": { @@ -5957,7 +7157,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.60" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.50" }, "funding": [ { @@ -5981,7 +7181,7 @@ "type": "tidelift" } ], - "time": "2025-12-06T07:50:42+00:00" + "time": "2026-01-27T05:59:18+00:00" }, { "name": "psr/cache", @@ -6032,18 +7232,69 @@ }, "time": "2021-02-03T23:26:27+00:00" }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, { "name": "roave/security-advisories", "version": "dev-master", "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "95fda149b750941a5d7bd292e712107ca3227a04" + "reference": "c4162b6092bc6170cc6d0758ba6ee7d29d0dfbb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/95fda149b750941a5d7bd292e712107ca3227a04", - "reference": "95fda149b750941a5d7bd292e712107ca3227a04", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/c4162b6092bc6170cc6d0758ba6ee7d29d0dfbb8", + "reference": "c4162b6092bc6170cc6d0758ba6ee7d29d0dfbb8", "shasum": "" }, "conflict": { @@ -6139,7 +7390,7 @@ "bytefury/crater": "<6.0.2", "cachethq/cachet": "<2.5.1", "cadmium-org/cadmium-cms": "<=0.4.9", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|>=5.2.10,<5.2.12|==5.3", "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", "cardgate/magento2": "<2.0.33", "cardgate/woocommerce": "<=3.1.15", @@ -6178,10 +7429,11 @@ "contao/core-bundle": "<4.13.57|>=5,<5.3.42|>=5.4,<5.6.5", "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", "contao/managed-edition": "<=1.5", - "coreshop/core-shop": "<=4.1.7", + "coreshop/core-shop": "<4.1.9", "corveda/phpsandbox": "<1.3.5", "cosenary/instagram": "<=2.3", "couleurcitron/tarteaucitron-wp": "<0.3", + "cpsit/typo3-mailqueue": "<0.4.3|>=0.5,<0.5.1", "craftcms/cms": "<=4.16.16|>=5,<=5.8.20", "croogo/croogo": "<=4.0.7", "cuyz/valinor": "<0.12", @@ -6260,7 +7512,7 @@ "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.1.2", "ecodev/newsletter": "<=4", "ectouch/ectouch": "<=2.7.2", - "egroupware/egroupware": "<23.1.20240624", + "egroupware/egroupware": "<23.1.20260113|>=26.0.20251208,<26.0.20260113", "elefant/cms": "<2.0.7", "elgg/elgg": "<3.3.24|>=4,<4.0.5", "elijaa/phpmemcacheadmin": "<=1.3", @@ -6435,7 +7687,7 @@ "kelvinmo/simplexrd": "<3.1.1", "kevinpapst/kimai2": "<1.16.7", "khodakhah/nodcms": "<=3", - "kimai/kimai": "<=2.20.1", + "kimai/kimai": "<2.46", "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", "klaviyo/magento2-extension": ">=1,<3", "knplabs/knp-snappy": "<=1.4.2", @@ -6454,10 +7706,10 @@ "laravel/framework": "<10.48.29|>=11,<11.44.1|>=12,<12.1.1", "laravel/laravel": ">=5.4,<5.4.22", "laravel/pulse": "<1.3.1", - "laravel/reverb": "<1.4", + "laravel/reverb": "<1.7", "laravel/socialite": ">=1,<2.0.10", "latte/latte": "<2.10.8", - "lavalite/cms": "<=9|==10.1", + "lavalite/cms": "<=10.1", "lavitto/typo3-form-to-database": "<2.2.5|>=3,<3.2.2|>=4,<4.2.3|>=5,<5.0.2", "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", "league/commonmark": "<2.7", @@ -6471,6 +7723,7 @@ "lightsaml/lightsaml": "<1.3.5", "limesurvey/limesurvey": "<6.5.12", "livehelperchat/livehelperchat": "<=3.91", + "livewire-filemanager/filemanager": "<=1.0.4", "livewire/livewire": "<2.12.7|>=3.0.0.0-beta1,<3.6.4", "livewire/volt": "<1.7", "lms/routes": "<2.1.1", @@ -6529,7 +7782,7 @@ "mongodb/mongodb": ">=1,<1.9.2", "mongodb/mongodb-extension": "<1.21.2", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.4.11|>=4.5.0.0-beta,<4.5.7|>=5.0.0.0-beta,<5.0.3", + "moodle/moodle": "<4.4.12|>=4.5.0.0-beta,<4.5.8|>=5.0.0.0-beta,<5.0.4|>=5.1.0.0-beta,<5.1.1", "moonshine/moonshine": "<=3.12.5", "mos/cimage": "<0.7.19", "movim/moxl": ">=0.8,<=0.10", @@ -6614,6 +7867,7 @@ "pear/pear": "<=1.10.1", "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", "personnummer/personnummer": "<3.0.2", + "ph7software/ph7builder": "<=17.9.1", "phanan/koel": "<5.1.4", "phenx/php-svg-lib": "<0.5.2", "php-censor/php-censor": "<2.0.13|>=2.1,<2.1.5", @@ -6624,7 +7878,7 @@ "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", "phpmyadmin/phpmyadmin": "<5.2.2", - "phpmyfaq/phpmyfaq": "<=4.0.13", + "phpmyfaq/phpmyfaq": "<=4.0.16", "phpoffice/common": "<0.2.9", "phpoffice/math": "<=0.2", "phpoffice/phpexcel": "<=1.8.2", @@ -6633,7 +7887,7 @@ "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", "phpservermon/phpservermon": "<3.6", "phpsysinfo/phpsysinfo": "<3.4.3", - "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpunit/phpunit": "<8.5.52|>=9,<9.6.33|>=10,<10.5.62|>=11,<11.5.50|>=12,<12.5.8", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", "phpxmlrpc/phpxmlrpc": "<4.9.2", @@ -6758,7 +8012,7 @@ "snipe/snipe-it": "<=8.3.4", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", - "solspace/craft-freeform": "<4.1.29|>=5,<5.10.16", + "solspace/craft-freeform": "<4.1.29|>=5,<=5.14.6", "soosyze/soosyze": "<=2", "spatie/browsershot": "<5.0.5", "spatie/image-optimizer": "<1.7.3", @@ -6812,7 +8066,7 @@ "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/polyfill": ">=1,<1.10", "symfony/polyfill-php55": ">=1,<1.10", - "symfony/process": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/process": "<5.4.51|>=6,<6.4.33|>=7,<7.1.7|>=7.3,<7.3.11|>=7.4,<7.4.5|>=8,<8.0.5", "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/routing": ">=2,<2.0.19", "symfony/runtime": ">=5.3,<5.4.46|>=6,<6.4.14|>=7,<7.1.7", @@ -6823,7 +8077,7 @@ "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", - "symfony/symfony": "<5.4.50|>=6,<6.4.29|>=7,<7.3.7", + "symfony/symfony": "<5.4.51|>=6,<6.4.33|>=7,<7.3.11|>=7.4,<7.4.5|>=8,<8.0.5", "symfony/translation": ">=2,<2.0.17", "symfony/twig-bridge": ">=2,<4.4.51|>=5,<5.4.31|>=6,<6.3.8", "symfony/ux-autocomplete": "<2.11.2", @@ -6847,7 +8101,7 @@ "thelia/thelia": ">=2.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", "thinkcmf/thinkcmf": "<6.0.8", - "thorsten/phpmyfaq": "<4.0.16|>=4.1.0.0-alpha,<=4.1.0.0-beta2", + "thorsten/phpmyfaq": "<=4.0.16|>=4.1.0.0-alpha,<=4.1.0.0-beta2", "tikiwiki/tiki-manager": "<=17.1", "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", "tinymce/tinymce": "<7.2", @@ -7041,32 +8295,32 @@ "type": "tidelift" } ], - "time": "2026-01-15T23:06:28+00:00" + "time": "2026-01-28T22:08:32+00:00" }, { "name": "sebastian/cli-parser", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -7090,7 +8344,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { @@ -7098,32 +8352,32 @@ "type": "github" } ], - "time": "2024-03-02T07:12:49+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { "name": "sebastian/code-unit", - "version": "2.0.0", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -7146,7 +8400,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" }, "funding": [ { @@ -7154,32 +8409,32 @@ "type": "github" } ], - "time": "2023-02-03T06:58:43+00:00" + "time": "2025-03-19T07:56:08+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -7201,7 +8456,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { @@ -7209,36 +8465,39 @@ "type": "github" } ], - "time": "2023-02-03T06:59:15+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { "name": "sebastian/comparator", - "version": "5.0.4", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e" + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e8e53097718d2b53cfb2aa859b06a41abf58c62e", - "reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -7278,7 +8537,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.4" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3" }, "funding": [ { @@ -7298,33 +8557,33 @@ "type": "tidelift" } ], - "time": "2025-09-07T05:25:07+00:00" + "time": "2026-01-24T09:26:40+00:00" }, { "name": "sebastian/complexity", - "version": "3.2.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -7348,7 +8607,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -7356,33 +8615,33 @@ "type": "github" } ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "5.1.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -7415,7 +8674,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -7423,27 +8682,27 @@ "type": "github" } ], - "time": "2024-03-02T07:15:17+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "6.1.0", + "version": "7.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "suggest": { "ext-posix": "*" @@ -7451,7 +8710,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -7479,42 +8738,54 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" } ], - "time": "2024-03-23T08:47:14+00:00" + "time": "2025-05-21T11:55:47+00:00" }, { "name": "sebastian/exporter", - "version": "5.1.4", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "0735b90f4da94969541dac1da743446e276defa6" + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", - "reference": "0735b90f4da94969541dac1da743446e276defa6", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -7557,7 +8828,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2" }, "funding": [ { @@ -7577,35 +8848,35 @@ "type": "tidelift" } ], - "time": "2025-09-24T06:09:11+00:00" + "time": "2025-09-24T06:12:51+00:00" }, { "name": "sebastian/global-state", - "version": "6.0.2", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -7631,7 +8902,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { @@ -7639,33 +8910,33 @@ "type": "github" } ], - "time": "2024-03-02T07:19:19+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", - "version": "2.0.2", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -7689,7 +8960,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -7697,34 +8968,34 @@ "type": "github" } ], - "time": "2023-12-21T08:38:20+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", - "version": "5.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -7746,7 +9017,8 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { @@ -7754,32 +9026,32 @@ "type": "github" } ], - "time": "2023-02-03T07:08:32+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -7801,7 +9073,8 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { @@ -7809,32 +9082,32 @@ "type": "github" } ], - "time": "2023-02-03T07:06:18+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", - "version": "5.0.1", + "version": "6.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", - "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -7865,7 +9138,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" }, "funding": [ { @@ -7885,32 +9158,32 @@ "type": "tidelift" } ], - "time": "2025-08-10T07:50:56+00:00" + "time": "2025-08-13T04:42:22+00:00" }, { "name": "sebastian/type", - "version": "4.0.0", + "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -7933,37 +9206,50 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" } ], - "time": "2023-02-03T07:10:45+00:00" + "time": "2025-08-09T06:55:48+00:00" }, { "name": "sebastian/version", - "version": "4.0.1", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -7986,7 +9272,8 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -7994,36 +9281,36 @@ "type": "github" } ], - "time": "2023-02-07T11:34:05+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { "name": "slevomat/coding-standard", - "version": "8.26.0", + "version": "8.27.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "d247cdc04b91956bdcfaa0b1313c01960b189d3c" + "reference": "29bdaee8b65e7ed2b8e702b01852edba8bae1769" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/d247cdc04b91956bdcfaa0b1313c01960b189d3c", - "reference": "d247cdc04b91956bdcfaa0b1313c01960b189d3c", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/29bdaee8b65e7ed2b8e702b01852edba8bae1769", + "reference": "29bdaee8b65e7ed2b8e702b01852edba8bae1769", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.2.0", "php": "^7.4 || ^8.0", - "phpstan/phpdoc-parser": "^2.3.0", + "phpstan/phpdoc-parser": "^2.3.1", "squizlabs/php_codesniffer": "^4.0.1" }, "require-dev": { - "phing/phing": "3.0.1|3.1.0", + "phing/phing": "3.0.1|3.1.1", "php-parallel-lint/php-parallel-lint": "1.4.0", - "phpstan/phpstan": "2.1.33", + "phpstan/phpstan": "2.1.37", "phpstan/phpstan-deprecation-rules": "2.0.3", - "phpstan/phpstan-phpunit": "2.0.11", + "phpstan/phpstan-phpunit": "2.0.12", "phpstan/phpstan-strict-rules": "2.0.7", - "phpunit/phpunit": "9.6.31|10.5.60|11.4.4|11.5.46|12.5.4" + "phpunit/phpunit": "9.6.31|10.5.60|11.4.4|11.5.49|12.5.7" }, "type": "phpcodesniffer-standard", "extra": { @@ -8047,7 +9334,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.26.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.27.1" }, "funding": [ { @@ -8059,32 +9346,33 @@ "type": "tidelift" } ], - "time": "2025-12-21T18:01:15+00:00" + "time": "2026-01-25T15:57:07+00:00" }, { "name": "softcreatr/jsonpath", - "version": "0.8.3", + "version": "0.9.1", "source": { "type": "git", "url": "https://github.com/SoftCreatR/JSONPath.git", - "reference": "fc12dee0b46f3fa3a175c4051dbab60984acef4b" + "reference": "272173a65fd16b25010dbd54d04dd34c0c5a8500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SoftCreatR/JSONPath/zipball/fc12dee0b46f3fa3a175c4051dbab60984acef4b", - "reference": "fc12dee0b46f3fa3a175c4051dbab60984acef4b", + "url": "https://api.github.com/repos/SoftCreatR/JSONPath/zipball/272173a65fd16b25010dbd54d04dd34c0c5a8500", + "reference": "272173a65fd16b25010dbd54d04dd34c0c5a8500", "shasum": "" }, "require": { "ext-json": "*", - "php": ">=8.0" + "php": "8.1 - 8.4" }, "replace": { "flow/jsonpath": "*" }, "require-dev": { - "phpunit/phpunit": "^9.6", - "roave/security-advisories": "dev-latest" + "friendsofphp/php-cs-fixer": "^3.58", + "phpunit/phpunit": "10 - 12", + "squizlabs/php_codesniffer": "^3.10" }, "type": "library", "autoload": { @@ -8127,7 +9415,7 @@ "type": "github" } ], - "time": "2023-08-17T20:14:00+00:00" + "time": "2024-06-01T09:15:21+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -8208,18 +9496,70 @@ ], "time": "2025-11-10T16:43:36+00:00" }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, { "name": "symfony/cache", - "version": "v7.4.3", + "version": "v7.4.5", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "642117d18bc56832e74b68235359ccefab03dd11" + "reference": "8dde98d5a4123b53877aca493f9be57b333f14bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/642117d18bc56832e74b68235359ccefab03dd11", - "reference": "642117d18bc56832e74b68235359ccefab03dd11", + "url": "https://api.github.com/repos/symfony/cache/zipball/8dde98d5a4123b53877aca493f9be57b333f14bd", + "reference": "8dde98d5a4123b53877aca493f9be57b333f14bd", "shasum": "" }, "require": { @@ -8290,7 +9630,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.4.3" + "source": "https://github.com/symfony/cache/tree/v7.4.5" }, "funding": [ { @@ -8310,7 +9650,7 @@ "type": "tidelift" } ], - "time": "2025-12-28T10:45:24+00:00" + "time": "2026-01-27T16:16:02+00:00" }, { "name": "symfony/cache-contracts", @@ -8605,6 +9945,65 @@ ], "time": "2025-11-05T18:53:00+00:00" }, + { + "name": "ta-tikoma/phpunit-architecture-test", + "version": "0.8.6", + "source": { + "type": "git", + "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", + "reference": "ad48430b92901fd7d003fdaf2d7b139f96c0906e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/ad48430b92901fd7d003fdaf2d7b139f96c0906e", + "reference": "ad48430b92901fd7d003fdaf2d7b139f96c0906e", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18.0 || ^5.0.0", + "php": "^8.1.0", + "phpdocumentor/reflection-docblock": "^5.3.0 || ^6.0.0", + "phpunit/phpunit": "^10.5.5 || ^11.0.0 || ^12.0.0", + "symfony/finder": "^6.4.0 || ^7.0.0 || ^8.0.0" + }, + "require-dev": { + "laravel/pint": "^1.13.7", + "phpstan/phpstan": "^1.10.52" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPUnit\\Architecture\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ni Shi", + "email": "futik0ma011@gmail.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Methods for testing application architecture", + "keywords": [ + "architecture", + "phpunit", + "stucture", + "test", + "testing" + ], + "support": { + "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", + "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.6" + }, + "time": "2026-01-30T07:16:00+00:00" + }, { "name": "theseer/tokenizer", "version": "1.3.1", diff --git a/config/autoload/dependencies.global.php b/config/autoload/dependencies.global.php index 638d5c2a..3b95d586 100644 --- a/config/autoload/dependencies.global.php +++ b/config/autoload/dependencies.global.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Exdrals\Shared\Infrastructure\Factory\MailFactory; use Mezzio\Application; use Mezzio\Container\ApplicationConfigInjectionDelegator; use Exdrals\Shared\Infrastructure\Factory\DatabaseFactory; diff --git a/config/autoload/dependencies.testing.php b/config/autoload/dependencies.testing.php index 9899a342..fe3a0178 100644 --- a/config/autoload/dependencies.testing.php +++ b/config/autoload/dependencies.testing.php @@ -1,23 +1,36 @@ - [ + // Use 'aliases' to alias a service name to another service. The + // key is the alias name, the value is the service to which it points. 'aliases' => [ PDO::class => 'database', Envms\FluentPDO\Query::class => 'query', - UuidFactoryInterface::class => 'uuid', Psr\Log\LoggerInterface::class => 'logger', - Symfony\Component\Mailer\MailerInterface::class => 'mailer', + UuidFactoryInterface::class => 'uuid', + \Symfony\Component\Mailer\MailerInterface::class => 'mailer', ], + // Use 'invokables' for constructor-less services, or services that do + // not require arguments to the constructor. Map a service name to the + // class name. 'invokables' => [ ], + // Use 'factories' for services provided by callbacks/factory classes. 'factories' => [ 'database' => DatabaseFactory::class, 'query' => QueryFactory::class, @@ -26,8 +39,8 @@ 'mailer' => NullMailerFactory::class, ], 'delegators' => [ - \Mezzio\Application::class => [ - \Mezzio\Container\ApplicationConfigInjectionDelegator::class, + Application::class => [ + ApplicationConfigInjectionDelegator::class, ], ], ], diff --git a/config/autoload/mail.testing.php b/config/autoload/mail.testing.php deleted file mode 100644 index 7a17007e..00000000 --- a/config/autoload/mail.testing.php +++ /dev/null @@ -1,8 +0,0 @@ - [ - 'dsn' => 'smtp://mailhog:1025', - 'from' => 'hackathon@exdrals.de', - ], -]; diff --git a/config/autoload/migrations.testing.php b/config/autoload/migrations.testing.php index 166dbab1..0626d103 100644 --- a/config/autoload/migrations.testing.php +++ b/config/autoload/migrations.testing.php @@ -12,7 +12,6 @@ 'migrations_paths' => [ 'Migrations' => __DIR__ . '/../../database/migrations', - 'TestDataMigrations' => __DIR__ . '/../../tests/FunctionalTest/database/migrations', ], 'all_or_nothing' => true, diff --git a/config/autoload/project.testing.php b/config/autoload/project.testing.php deleted file mode 100644 index 0ce3c9df..00000000 --- a/config/autoload/project.testing.php +++ /dev/null @@ -1,21 +0,0 @@ - [ - 'uri' => 'http://localhost', - ], - 'api' => [ - 'access' => [ - 'domain' => [ - 'whitelist' => [ - 'localhost', - ], - ], - ], - ], - 'event' => [ - 'participant' => [ - 'subscribe_delay' => 30, - ], - ], -]; diff --git a/config/autoload/token.global.php b/config/autoload/token.global.php new file mode 100644 index 00000000..18618d96 --- /dev/null +++ b/config/autoload/token.global.php @@ -0,0 +1,20 @@ + [ + 'refresh' => [ + 'key' => 'ixo>+W%!Rf/\@)m2UMok:/A_gL 'HS512', + 'duration' => 60 * 60 * 24 * 7 * 12, + 'iss' => 'localhost', + 'aud' => 'localhost', + ], + 'access' => [ + 'key' => 'b:?Y@5JCWF:yi{o>irc(3$HFcR-#b\SA', + 'algorithmus' => 'HS512', + 'duration' => 60 * 60, + 'iss' => 'localhost', + 'aud' => 'localhost', + ], + ], +]; diff --git a/config/autoload/token.testing.php b/config/autoload/token.testing.php index ec2b43e4..7eb79123 100644 --- a/config/autoload/token.testing.php +++ b/config/autoload/token.testing.php @@ -5,14 +5,14 @@ 'refresh' => [ 'key' => 'ixo>+W%!Rf/\@)m2UMok:/A_gL 'HS512', - 'duration' => 60 * 60 * 24 * 7 * 12, + 'duration' => 60 * 60 * 60 * 100000, 'iss' => 'localhost', 'aud' => 'localhost', ], 'access' => [ 'key' => 'b:?Y@5JCWF:yi{o>irc(3$HFcR-#b\SA', 'algorithmus' => 'HS512', - 'duration' => 60 * 5, + 'duration' => 60 * 60, 'iss' => 'localhost', 'aud' => 'localhost', ], diff --git a/config/config.php b/config/config.php index baec7a7a..b7bb7b0a 100644 --- a/config/config.php +++ b/config/config.php @@ -48,6 +48,7 @@ class_exists(\Mezzio\Swoole\ConfigProvider::class) getenv('APP_ENV') ?: 'production' ) ), + // Load development config if it exists new PhpFileProvider(realpath(__DIR__) . '/development.config.php'), ], $cacheConfig['config_cache_path']); diff --git a/docker/php/php-ini-overrides.ini b/docker/php/php-ini-overrides.ini index 92aa2697..7c27d0c6 100644 --- a/docker/php/php-ini-overrides.ini +++ b/docker/php/php-ini-overrides.ini @@ -1,5 +1,5 @@ xdebug.client_port=9000 -xdebug.mode=develop,debug,trace,profile,gcstats +xdebug.mode=develop,debug,trace,profile,gcstats,coverage xdebug.start_with_request=trigger xdebug.discover_client_host=On error_reporting=E_ALL diff --git a/phpstan.neon b/phpstan.neon index e417e175..75771b1d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -11,6 +11,9 @@ parameters: checkUninitializedProperties: true tips: treatPhpDocTypesAsCertain: false + excludePaths: + - tests/* + - tests rules: - PHPStan\Rules\Functions\ReturnNullsafeByRefRule includes: diff --git a/src/App/Account/Identity/src/ConfigProvider.php b/src/App/Account/Identity/src/ConfigProvider.php index 8843365b..5c2f1034 100644 --- a/src/App/Account/Identity/src/ConfigProvider.php +++ b/src/App/Account/Identity/src/ConfigProvider.php @@ -21,6 +21,7 @@ use Exdrals\Identity\Infrastructure\Service\Token\ActivationTokenService; use Exdrals\Identity\Infrastructure\Service\Token\PasswordTokenService; use Exdrals\Identity\Infrastructure\Service\Token\RefreshTokenService; +use Exdrals\Identity\Infrastructure\Service\Token\RefreshTokenServiceInterface; use Exdrals\Identity\Infrastructure\Validator\AccountActivationValidator; use Exdrals\Identity\Infrastructure\Validator\AuthenticationValidator; use Exdrals\Identity\Infrastructure\Validator\Input\AccountNameInput; @@ -43,6 +44,7 @@ use Exdrals\Shared\Infrastructure\Persistence\Store\Account\AccountActivationStoreInterface; use Exdrals\Shared\Infrastructure\Persistence\Store\Account\AccountStoreInterface; use Exdrals\Shared\Infrastructure\Persistence\Store\Token\TokenStoreInterface; +use Exdrals\Shared\Middleware\FluentTransactionMiddleware; use Exdrals\Shared\Middleware\RequireLoginMiddleware; use Exdrals\Shared\Utils\UuidFactoryInterface; use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory; @@ -65,60 +67,55 @@ public function getRoutes(): array { return [ [ - 'path' => '/api/token/refresh[/]', - 'allowed_methods' => ['GET'], + 'path' => '/api/account[/]', + 'allowed_methods' => ['POST'], 'middleware' => [ - Middleware\Token\RefreshTokenValidationMiddleware::class, Middleware\IdentityExceptionMappingMiddleware::class, - Handler\AccessTokenHandler::class, + Middleware\Account\Validation\EmailInputValidatorMiddleware::class, + Handler\AccountRegisterHandler::class, ], - 'name' => 'api_identity_token_refresh', + 'name' => 'api_identity_register', ], [ - 'path' => '/api/account/authentication[/]', + 'path' => '/api/account/activation/[{token}[/]]', 'allowed_methods' => ['POST'], 'middleware' => [ - Middleware\Account\Authentication\AuthenticationConditionsMiddleware::class, - Middleware\Account\Authentication\AuthenticationValidationMiddleware::class, Middleware\IdentityExceptionMappingMiddleware::class, - Handler\AuthenticationHandler::class, + Middleware\Account\Validation\ActivationInputValidatorMiddleware::class, + FluentTransactionMiddleware::class, + Handler\AccountActivationHandler::class, ], - 'name' => 'api_identity_authentication', + 'name' => 'api_identity_activation', ], + [ - 'path' => '/api/account[/]', + 'path' => '/api/account/authentication[/]', 'allowed_methods' => ['POST'], 'middleware' => [ - Middleware\Account\Validation\EmailInputValidatorMiddleware::class, Middleware\IdentityExceptionMappingMiddleware::class, - Handler\AccountRegisterHandler::class, + Middleware\Account\Authentication\AuthenticationConditionsMiddleware::class, + Middleware\Account\Authentication\AuthenticationValidationMiddleware::class, + Handler\AuthenticationHandler::class, ], - 'name' => 'api_identity_register', + 'name' => 'api_identity_authentication', ], [ - 'path' => '/api/account/[{accountUuid:[0-9a-fA-F\-]+}[/]]', + 'path' => '/api/token/refresh[/]', 'allowed_methods' => ['GET'], 'middleware' => [ - RequireLoginMiddleware::class, - ], - 'name' => 'api_account_detail', - ], - [ - 'path' => '/api/account/activation/[{token}[/]]', - 'allowed_methods' => ['POST'], - 'middleware' => [ - Middleware\Account\Validation\ActivationInputValidatorMiddleware::class, Middleware\IdentityExceptionMappingMiddleware::class, - Handler\AccountActivationHandler::class, + Middleware\Token\RefreshTokenValidationMiddleware::class, + Handler\AccessTokenHandler::class, ], - 'name' => 'api_identity_activation', + 'name' => 'api_identity_token_refresh', ], + [ 'path' => '/api/account/password/forgotten[/]', 'allowed_methods' => ['POST'], 'middleware' => [ + Middleware\IdentityExceptionMappingMiddleware::class, Middleware\Account\Validation\EmailInputValidatorMiddleware::class, - IdentityExceptionMappingMiddleware::class, Handler\AccountPasswordForgottenHandler::class, ], 'name' => 'api_identity_password_forgotten', @@ -127,23 +124,33 @@ public function getRoutes(): array 'path' => '/api/account/password/[{token}[/]]', 'allowed_methods' => ['PATCH'], 'middleware' => [ + Middleware\IdentityExceptionMappingMiddleware::class, Middleware\Account\Validation\PasswordInputValidatorMiddleware::class, - IdentityExceptionMappingMiddleware::class, Handler\AccountPasswordHandler::class, ], 'name' => 'api_identity_password_change', ], + [ 'path' => '/api/account/logout[/]', 'allowed_methods' => ['GET'], 'middleware' => [ + Middleware\IdentityExceptionMappingMiddleware::class, RequireLoginMiddleware::class, Middleware\Token\AccessTokenValidationMiddleware::class, - IdentityExceptionMappingMiddleware::class, Handler\LogoutHandler::class, ], 'name' => 'api_identity_logout', ], + [ + 'path' => '/api/account/[{accountUuid:[0-9a-fA-F\-]+}[/]]', + 'allowed_methods' => ['GET'], + 'middleware' => [ + Middleware\IdentityExceptionMappingMiddleware::class, + RequireLoginMiddleware::class, + ], + 'name' => 'api_account_detail', + ], ]; } diff --git a/src/App/Account/Identity/src/Domain/Message/IdentityLogMessage.php b/src/App/Account/Identity/src/Domain/Message/IdentityLogMessage.php index 628a0613..701af59a 100644 --- a/src/App/Account/Identity/src/Domain/Message/IdentityLogMessage.php +++ b/src/App/Account/Identity/src/Domain/Message/IdentityLogMessage.php @@ -47,6 +47,7 @@ interface IdentityLogMessage extends LogMessage // --- 8. Refresh Tokens --- public const string REFRESH_TOKEN_MISSING = 'No refresh token provided'; public const string REFRESH_TOKEN_INVALID = 'The provided refresh token is invalid'; + public const string REFRESH_TOKEN_EXPIRED = 'The provided refresh token is expired'; public const string REFRESH_TOKEN_NOT_FOUND = 'The provided refresh token is unrecognized'; public const string REFRESH_TOKEN_CLIENT_MISMATCH = 'The refresh token was issued to a different client'; public const string REFRESH_TOKEN_ACCOUNT_NOT_FOUND = 'The account associated with the refresh token was not found'; diff --git a/src/App/Account/Identity/src/Handler/AccountRegisterHandler.php b/src/App/Account/Identity/src/Handler/AccountRegisterHandler.php index 6fcf0701..f74baec8 100644 --- a/src/App/Account/Identity/src/Handler/AccountRegisterHandler.php +++ b/src/App/Account/Identity/src/Handler/AccountRegisterHandler.php @@ -3,7 +3,7 @@ namespace Exdrals\Identity\Handler; use Exdrals\Identity\DTO\EMail\EMail; -use Exdrals\Identity\Infrastructure\Service\Account\AccountRegisterService; +use Exdrals\Identity\Infrastructure\Service\Account\AccountRegisterServiceInterface; use Exdrals\Mailing\Domain\EmailType; use Fig\Http\Message\StatusCodeInterface as HTTP; use Laminas\Diactoros\Response\JsonResponse; @@ -15,7 +15,7 @@ readonly class AccountRegisterHandler implements RequestHandlerInterface { public function __construct( - private AccountRegisterService $accountRegisterService, + private AccountRegisterServiceInterface $accountRegisterService, ) { } diff --git a/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountRegisterService.php b/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountRegisterService.php index e8ab2bd3..a449a79f 100644 --- a/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountRegisterService.php +++ b/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountRegisterService.php @@ -10,7 +10,7 @@ use Exdrals\Shared\Infrastructure\Persistence\Repository\Account\AccountActivationRepositoryInterface; use Exdrals\Shared\Utils\UuidFactoryInterface; -readonly class AccountRegisterService +readonly class AccountRegisterService implements AccountRegisterServiceInterface { public function __construct( private AccountService $accountService, diff --git a/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountRegisterServiceInterface.php b/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountRegisterServiceInterface.php new file mode 100644 index 00000000..d236f60b --- /dev/null +++ b/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountRegisterServiceInterface.php @@ -0,0 +1,10 @@ +mailValidator->getValues()['email']); } catch (InvalidArgumentException) { throw new HttpInvalidArgumentException( IdentityLogMessage::EMAIL_INVALID, diff --git a/src/Shared/src/Handler/PingHandler.php b/src/Shared/src/Handler/PingHandler.php index a2814a49..0bd47243 100644 --- a/src/Shared/src/Handler/PingHandler.php +++ b/src/Shared/src/Handler/PingHandler.php @@ -39,6 +39,10 @@ )] public function handle(ServerRequestInterface $request): ResponseInterface { - return new JsonResponse(['ack' => time()]); + return new JsonResponse([ + 'ack' => time(), + 'message' => 'pong', + 'php_version' => PHP_VERSION, + ]); } } diff --git a/tests/FunctionalTest/Root/Account/AccountActivationHandlerTest.php b/tests/FunctionalTest/Root/Account/AccountActivationHandlerTest.php deleted file mode 100644 index d0b68f68..00000000 --- a/tests/FunctionalTest/Root/Account/AccountActivationHandlerTest.php +++ /dev/null @@ -1,119 +0,0 @@ -container->get(UuidFactoryInterface::class); - - /** @var AccountActivationRepositoryInterface $activationRepository */ - $activationRepository = $this->container->get(AccountActivationRepositoryInterface::class); - - $testAccountActivate = new AccountActivation( - id: null, - email: new EmailType('test@example.com'), - token: $uuid->uuid7(), - createdAt: new DateTimeImmutable() - ); - - $activationRepository->insert($testAccountActivate); - - $request = new ServerRequest( - uri: '/api/account/activation/' . $testAccountActivate->token->toString(), - method: 'POST' - ); - $request = $request->withParsedBody([ - 'accountName' => 'Test', - 'password' => 'TestBlaBlubb', - ]); - $response = $this->app->handle($request); - - $emptyAccountActivate = $activationRepository->findByToken( - $testAccountActivate->token->toString() - ); - - $this->assertSame(HTTP::STATUS_CREATED, $response->getStatusCode()); - $this->assertNull($emptyAccountActivate); - } - - public function testTokenNotGiven(): void - { - $request = new ServerRequest( - uri: '/api/account/activation/', - method: 'POST' - ); - $request = $request->withParsedBody([ - 'accountName' => 'Test', - 'password' => 'TestBlaBlubb', - ]); - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::TOKEN_INVALID, $content['message']); - } - - public function testBodyIsInvalid(): void - { - $request = new ServerRequest( - uri: '/api/account/activation/', - method: 'POST' - ); - - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::INVALID_DATA, $content['message']); - } - - public function testTokenIsInvalidOrNotPersistent(): void - { - $request = new ServerRequest( - uri: '/api/account/activation/1ddwrer2', - method: 'POST' - ); - $request = $request->withParsedBody([ - 'accountName' => 'Test', - 'password' => 'TestBlaBlubb', - ]); - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::TOKEN_INVALID, $content['message']); - } -} diff --git a/tests/FunctionalTest/Root/Account/AccountRegisterHandlerTest.php b/tests/FunctionalTest/Root/Account/AccountRegisterHandlerTest.php deleted file mode 100644 index 3a155ddb..00000000 --- a/tests/FunctionalTest/Root/Account/AccountRegisterHandlerTest.php +++ /dev/null @@ -1,104 +0,0 @@ -app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::INVALID_DATA, $content['message']); - } - - public function testBodyHasInvalidParameter(): void - { - $request = new ServerRequest( - uri: '/api/account', - method: 'POST' - ); - - $response = $this->app->handle($request); - $request = $request->withParsedBody(['password' => 'password']); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::INVALID_DATA, $content['message']); - } - - public function testActivationDataSetWasCreated(): void - { - $request = new ServerRequest( - uri: '/api/account', - method: 'POST' - ); - $request = $request->withParsedBody(['email' => 'Tester@example.com']); - $response = $this->app->handle($request); - - /** @var AccountActivationRepositoryInterface $repository */ - $repository = $this->container->get(AccountActivationRepositoryInterface::class); - $activationDataSet = $repository->findEmail(new EmailType('Tester@example.com')); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - $this->assertArrayHasKey(0, $activationDataSet); - $this->assertInstanceOf(AccountActivationInterface::class, $activationDataSet[0]); - } - - public function testPasswordDataSetWasCreated(): void - { - /** @var AccountRepositoryInterface $accountRepository */ - $accountRepository = $this->container->get(AccountRepositoryInterface::class); - $account = $accountRepository->findByEmail(new EmailType('user@example.com')); - - /** @var TokenRepositoryInterface $tokenRepository */ - $tokenRepository = $this->container->get(TokenRepositoryInterface::class); - $tokenRepository->deleteByAccountId($account->id); - - $request = new ServerRequest( - uri: '/api/account', - method: 'POST' - ); - $request = $request->withParsedBody(['email' => 'user@example.com']); - $response = $this->app->handle($request); - - $activationDataSet = $tokenRepository->findByAccountId($account->id); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - $this->assertArrayHasKey(0, $activationDataSet); - $this->assertInstanceOf(TokenInterface::class, $activationDataSet[0]); - } -} diff --git a/tests/FunctionalTest/Root/Account/AuthenticationHandlerTest.php b/tests/FunctionalTest/Root/Account/AuthenticationHandlerTest.php deleted file mode 100644 index eb4544ab..00000000 --- a/tests/FunctionalTest/Root/Account/AuthenticationHandlerTest.php +++ /dev/null @@ -1,181 +0,0 @@ -withParsedBody(['email' => $email, 'password' => $password]) - ->withAddedHeader('x-ident', (string)rand()); - $response = $this->app->handle($request); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - } - - #[DataProvider('invalidAuthenticateDataProvider')] - public function testAuthenticateFailed(string $email, string $password): void - { - $request = new ServerRequest( - uri: '/api/account/authentication', - method: 'POST' - ); - $request = $request->withParsedBody(['email' => $email, 'password' => $password]) - ->withAddedHeader('x-ident', (string)rand()); - $response = $this->app->handle($request); - - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - } - - public function testNoDoubleSameLogins(): void - { - $request = new ServerRequest( - uri: '/api/account/authentication', - method: 'POST' - ); - $request = $request->withParsedBody(['email' => 'owner@example.com', 'password' => 'owner123456']) - ->withAddedHeader('x-ident', (string)rand()); - - $response = $this->app->handle($request); - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - - $response = $this->app->handle($request); - $this->assertSame(HTTP::STATUS_CONFLICT, $response->getStatusCode()); - } - - public function testAccountIsAlreadyAuthenticated(): void - { - $request = new ServerRequest( - uri: '/api/account/authentication', - method: 'POST' - ); - $request = $request->withParsedBody(['email' => 'owner@example.com', 'password' => 'owner123456']) - ->withAddedHeader('x-ident', (string)rand()) - ->withAddedHeader('Authentication', 'Authentication'); - - $response = $this->app->handle($request); - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - } - - public function testAccountIsAlreadyAuthorized(): void - { - $request = new ServerRequest( - uri: '/api/account/authentication', - method: 'POST' - ); - $request = $request->withParsedBody(['email' => 'admin@example.com', 'password' => 'admin123456']) - ->withAddedHeader('x-ident', (string)rand()) - ->withAddedHeader('Authorization', 'Authorization'); - - $response = $this->app->handle($request); - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - } - - public function testResponseHasValidAccessAndRefreshToken(): void - { - /** @var AccountRepositoryInterface $accountRepository */ - $accountRepository = $this->container->get(AccountRepositoryInterface::class); - - /** @var AccessTokenService $accessTokenService */ - $accessTokenService = $this->container->get(AccessTokenService::class); - - /** @var RefreshTokenService $refreshTokenService */ - $refreshTokenService = $this->container->get(RefreshTokenService::class); - - /** @var UuidFactoryInterface $uuid */ - $uuid = $this->container->get(UuidFactoryInterface::class); - - $account = new \Exdrals\Identity\Domain\Account( - null, - $uuid->uuid7(), - 'I see your Token', - password_hash('I see your Token', PASSWORD_DEFAULT), - new EmailType('iseeyourtoken@example.com'), - new DateTimeImmutable(), - new DateTimeImmutable() - ); - $accountRepository->insert($account); - - $request = new ServerRequest( - uri: '/api/account/authentication', - method: 'POST' - ); - $request = $request->withParsedBody( - ['email' => $account->email->toString(), 'password' => 'I see your Token'] - ); - - $response = $this->app->handle($request); - - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'accessToken' => Assert::isType('string'), - 'refreshToken' => Assert::isType('string'), - ])); - - $isAccessToken = $accessTokenService->isValid($content['accessToken']); - $isRefreshToken = $refreshTokenService->isValid($content['refreshToken']); - - $this->assertTrue($isAccessToken); - $this->assertTrue($isRefreshToken); - } - - public static function validAccountDataProvider(): array - { - return [ - 'Owner' => ['owner@example.com', 'owner123456'], - 'Administrator' => ['admin@example.com', 'admin123456'], - 'Moderator' => ['moderator@example.com', 'moderator'], - 'User' => ['user@example.com', 'user123456'], - 'Valid fixed Account Constant' => [Account::EMAIL, Account::PASSWORD_STRING,], - ]; - } - - public static function invalidAuthenticateDataProvider(): array - { - return [ - 'Empty Fields' => ['', ''], - 'Empty E-Mail' => ['', '123456'], - 'Empty Password' => ['account@example.com', ''], - 'No E-Mail' => ['no E-Mail', '123456'], - 'Invalid email prefixe' => ['abc..def@mail.com', '123456'], - 'Password too Short' => ['account@example.com', '123'], - 'Password too Long' => [ - 'account@example.com', - '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111' - . '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111' - . '111111111111111111111111111111111111111111111111111111', - ], - 'Account with bad Password' => ['owner@example.com', '123456'], - 'SQL Injection Comment one' => ["owner@example.com'--", '123456'], - 'SQL Injection Comment two' => ["owner@example.com';", '123456'], - ]; - } -} diff --git a/tests/FunctionalTest/Root/Account/InvalidEMailAddressProviderTrait.php b/tests/FunctionalTest/Root/Account/InvalidEMailAddressProviderTrait.php deleted file mode 100644 index b9387e25..00000000 --- a/tests/FunctionalTest/Root/Account/InvalidEMailAddressProviderTrait.php +++ /dev/null @@ -1,54 +0,0 @@ -withParsedBody(['email' => $email]); - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertSame(StatusMessage::INVALID_DATA, $content['message']); - } - - public static function invalidEMailAddressProvider(): array - { - return [ - 'Missing @ symbol' => ['invalidemail.com'], - 'Missing domain' => ['user@'], - 'Missing local part' => ['@domain.com'], - 'Consecutive dots' => ['user..name@domain.com'], - 'Invalid character in local part' => ['user:name@domain.com'], - 'Invalid character in domain' => ['user@domain!.com'], - 'Missing top-level domain' => ['user@domain'], - 'Space in local part' => ['user name@domain.com'], - 'Space in domain' => ['user@domain .com'], - 'Double dot in domain' => ['user@domain..com'], - 'Invalid character' => ['user@-domain.com'], - 'Invalid domain (example.invalid)' => ['test@example.invalid'], - 'Invalid top level domain (example.web)' => ['test@example.web'], - 'Trailing space' => ['test@example '], - 'Leading space' => [' test@example.com'], - ]; - } -} diff --git a/tests/Integration/App/Account/Identity/AccountActivationTest.php b/tests/Integration/App/Account/Identity/AccountActivationTest.php new file mode 100644 index 00000000..a7fc9d05 --- /dev/null +++ b/tests/Integration/App/Account/Identity/AccountActivationTest.php @@ -0,0 +1,96 @@ +createJsonPostRequest( + '/api/account/activation/' . $accountActivate['token'], + [ + 'accountName' => Faker::create()->unique()->name(), + 'password' => Faker::create()->password(8), + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_CREATED) + ->and('Account')->toHaveRecord(['email' => $accountActivate['email']]); +}); + +it('returns 400 when body is empty', function () { + $accountActivation = AccountActivationFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/activation/' . $accountActivation['token'], + [], + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +it('returns 400 when not token was assigned', function () { + $request = $this->createJsonPostRequest( + '/api/account/activation/', + [ + 'accountName' => Faker::create()->unique()->name(), + 'password' => Faker::create()->password(8), + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +it('returns 400 if the account name is invalid', function () { + $accountActivation = AccountActivationFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/activation/' . $accountActivation['token'], + [ + 'accountName' => Faker::create()->lexify('??'), + 'password' => Faker::create()->password(8), + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +it('returns 400 if the password is invalid', function () { + $accountActivation = AccountActivationFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/activation/' . $accountActivation['token'], + [ + 'accountName' => Faker::create()->name(), + 'password' => Faker::create()->password(1, 5), + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +it('returns 400 because token not found', function () { + $request = $this->createJsonPostRequest( + '/api/account/activation/' . Faker::create()->uuid(), + [ + 'accountName' => Faker::create()->name(), + 'password' => Faker::create()->password(8), + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +it('returns 409 when Accountname is duplicate', function () { + $accountActivation = AccountActivationFactory::create(); + $account = AccountFactory::create(); + + $request = $this->createJsonPostRequest( + '/api/account/activation/' . $accountActivation['token'], + [ + 'accountName' => $account['name'], + 'password' => Faker::create()->password(8), + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_CONFLICT); +}); diff --git a/tests/Integration/App/Account/Identity/AuthenticationTest.php b/tests/Integration/App/Account/Identity/AuthenticationTest.php new file mode 100644 index 00000000..6c42ed61 --- /dev/null +++ b/tests/Integration/App/Account/Identity/AuthenticationTest.php @@ -0,0 +1,188 @@ +createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + + $modifiedRequest = RequestPipingFactory::process( + ClientIdentificationMiddleware::class, + $request + ); + + $clientIdentifikation = $modifiedRequest->getAttribute(ClientIdentification::class); + + $response = $this->app->handle($request); + $json = JsonFactory::create($response); + expect($response->getStatusCode())->toBe(Http::STATUS_OK) + ->and('AccountAccessAuth')->toHaveRecord([ + 'accountId' => $account['id'], + 'clientIdentHash' => $clientIdentifikation->identificationHash, + 'refreshToken' => $json['refreshToken'], + ]) + ->and(JsonFactory::create($response)) + ->toBeArray() + ->toHaveKey('refreshToken') + ->toHaveKey('accessToken'); +}); + +test('Login failed because authentication is already set in the header', function () { + $account = AccountFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ) + ->withAddedHeader('x-ident', (string)rand()) + ->withAddedHeader('Authorization', 'Authorization'); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Login failed because there is already a login entry with the same identification in the database', function () { + $account = AccountFactory::create(); + $firstRequest = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + $secondRequest = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + + $this->app->handle($firstRequest); + $response = $this->app->handle($secondRequest); + + expect($response->getStatusCode())->toBe(Http::STATUS_CONFLICT); +}); + +test('Account can log in with different identifications at the same time', function () { + $account = AccountFactory::create(); + $firstRequest = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ) + ->withHeader('x-ident', (string)rand()); + + $secondRequest = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ) + ->withHeader('x-ident', (string)rand()); + + $modifiedFirstRequest = RequestPipingFactory::process( + ClientIdentificationMiddleware::class, + $firstRequest + ); + $modifiedSecondRequest = RequestPipingFactory::process( + ClientIdentificationMiddleware::class, + $secondRequest + ); + + $firstClientIdentifikation = $modifiedFirstRequest->getAttribute(ClientIdentification::class); + $secondClientIdentifikation = $modifiedSecondRequest->getAttribute(ClientIdentification::class); + + $this->app->handle($firstRequest); + $response = $this->app->handle($secondRequest); + + expect($response->getStatusCode())->toBe(Http::STATUS_OK) + ->and($firstClientIdentifikation->identificationHash)->not->toBe( + $secondClientIdentifikation->identificationHash + ) + ->and('AccountAccessAuth')->toHaveRecord([ + 'accountId' => $account['id'], + 'clientIdentHash' => $firstClientIdentifikation->identificationHash, + ]) + ->and('AccountAccessAuth')->toHaveRecord([ + 'accountId' => $account['id'], + 'clientIdentHash' => $secondClientIdentifikation->identificationHash, + ]); +}); + +test('Credentials have invalid email', function () { + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => Faker::create()->regexify('[a-z]{5}-at-[a-z]{5}\.de'), + 'password' => Faker::create()->password(8), + ] + ); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Credentials have invalid password', function () { + $account = AccountFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => Faker::create()->password(1, 5), + ] + ); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Credentials are missed', function () { + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + ] + ); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Account missing', function () { + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => Faker::create()->safeEmail(), + 'password' => Faker::create()->password(8), + ] + ); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); diff --git a/tests/Integration/App/Account/Identity/Factory/AccountAccessAuthFactory.php b/tests/Integration/App/Account/Identity/Factory/AccountAccessAuthFactory.php new file mode 100644 index 00000000..7be71cc3 --- /dev/null +++ b/tests/Integration/App/Account/Identity/Factory/AccountAccessAuthFactory.php @@ -0,0 +1,33 @@ +getContainer(); + $fluent = $container->get(Query::class); + $defaults = [ + 'accountId' => $attributes['accountId'] ?: Faker::create()->numberBetween(), + 'label' => 'default', + 'refreshToken' => Faker::create()->uuid(), + 'userAgent' => 'unknown', + 'clientIdentHash' => Faker::create()->uuid(), + 'createdAt' => new DateTimeImmutable()->format(DateTimeFormat::DEFAULT->value), + ]; + + $data = array_merge($defaults, $attributes); + + $id = $fluent->insertInto('AccountAccessAuth', $data)->execute(); + + $data['id'] = $id; + + return $data; + } +} diff --git a/tests/Integration/App/Account/Identity/Factory/AccountActivationFactory.php b/tests/Integration/App/Account/Identity/Factory/AccountActivationFactory.php new file mode 100644 index 00000000..db564602 --- /dev/null +++ b/tests/Integration/App/Account/Identity/Factory/AccountActivationFactory.php @@ -0,0 +1,33 @@ +getContainer(); + $fluent = $container->get(Query::class); + $uuid = $container->get(UuidFactoryInterface::class); + + $defaults = [ + 'email' => $faker->unique()->safeEmail(), + 'token' => $uuid->uuid7()->toString(), + 'createdAt' => new DateTimeImmutable()->format(DateTimeFormat::DEFAULT->value), + ]; + + $data = array_merge($defaults, $attributes); + + $id = $fluent->insertInto('AccountActivation', $data)->execute(); + $data['id'] = $id; + + return $data; + } +} diff --git a/tests/Integration/App/Account/Identity/Factory/AccountFactory.php b/tests/Integration/App/Account/Identity/Factory/AccountFactory.php new file mode 100644 index 00000000..c9f74ba0 --- /dev/null +++ b/tests/Integration/App/Account/Identity/Factory/AccountFactory.php @@ -0,0 +1,41 @@ +getContainer(); + $fluent = $container->get(Query::class); + $password = $faker->password(8); + $defaults = [ + 'uuid' => $faker->unique()->uuid(), + 'name' => $faker->unique()->name(), + 'email' => $faker->unique()->safeEmail(), + 'password' => password_hash($password, PASSWORD_BCRYPT), + ]; + + $data = array_merge($defaults, $attributes); + + $id = $fluent->insertInto('Account', $data)->execute(); + $data['id'] = $id; + $data['password'] = $password; + + return $data; + } + + public static function createMany(int $count, array $attributes = []): array + { + $accounts = []; + for ($i = 0; $i < $count; $i++) { + $accounts[] = self::create($attributes); + } + return $accounts; + } +} diff --git a/tests/Integration/App/Account/Identity/RegisterTest.php b/tests/Integration/App/Account/Identity/RegisterTest.php new file mode 100644 index 00000000..c53a70f5 --- /dev/null +++ b/tests/Integration/App/Account/Identity/RegisterTest.php @@ -0,0 +1,86 @@ +safeEmail(); + $request = $this->createJsonPostRequest( + '/api/account', + [ + 'email' => $email, + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_OK) + ->and('AccountActivation')->toHaveRecord(['email' => $email]); +}); + + +it('returns 400 when email is invalid', function ($email) { + $request = $this->createJsonPostRequest( + '/api/account', + [ + 'email' => $email, + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +})->with([ + 'invalidate.com', + 'user@', + '@domain.com', + 'user..name@domain.com', + 'user:name@domain.com', + 'user@domain!.com', + 'user@domain', + 'user name@domain.com', + 'user@domain .com', + 'user@domain..com', + 'user@-domain.com', + 'test@example.invalid', + 'test@example.web', +]); + +it('handles service exceptions through mapping middleware', function () { + $service = Mockery::mock(AccountRegisterServiceInterface::class); + $service->shouldReceive('register') + ->andThrow(new Exception('Database connection failed')); + $this->container->setService(AccountRegisterServiceInterface::class, $service); + $request = $this->createJsonPostRequest( + '/api/account', + [ + 'email' => Faker::create()->safeEmail(), + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_OK); +}); + +it('returns 400 when body is empty', function () { + $request = $this->createJsonPostRequest( + '/api/account', + [], + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +it('returns 400 when email address is duplicate', function () { + $account = AccountFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account', + [ + 'email' => $account['email'], + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_OK) + ->and('Account')->toHaveRecord(['email' => $account['email']]); +}); diff --git a/tests/Integration/App/Account/Identity/TokenRefreshTest.php b/tests/Integration/App/Account/Identity/TokenRefreshTest.php new file mode 100644 index 00000000..d7fb36a5 --- /dev/null +++ b/tests/Integration/App/Account/Identity/TokenRefreshTest.php @@ -0,0 +1,119 @@ +createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + + $response = $this->app->handle($request); + $json = JsonFactory::create($response); + + $request = $this->createGetRequest( + '/api/token/refresh' + ) + ->withHeader('Authentication', $json['refreshToken']); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_OK) + ->and(JsonFactory::create($response)) + ->toBeArray() + ->toHaveKey('accessToken'); +}); + +test('Refresh token is invalid', function () { + $account = AccountFactory::create(); + $request = $this->createGetRequest( + '/api/token/refresh' + ) + ->withHeader('Authentication', INVALID_TOKEN); + + $modifiedRequest = RequestPipingFactory::process( + ClientIdentificationMiddleware::class, + $request + ); + + $clientIdentifikation = $modifiedRequest->getAttribute(ClientIdentification::class); + + AccountAccessAuthFactory::create([ + 'accountId' => $account['id'], + 'refreshToken' => EXPIRED_TOKEN, + 'clientIdentHash' => $clientIdentifikation->identificationHash, + ]); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Refresh Token is expired', function () { + $account = AccountFactory::create(); + $request = $this->createGetRequest( + '/api/token/refresh' + ) + ->withHeader('Authentication', EXPIRED_TOKEN); + + $modifiedRequest = RequestPipingFactory::process( + ClientIdentificationMiddleware::class, + $request + ); + + $clientIdentifikation = $modifiedRequest->getAttribute(ClientIdentification::class); + + AccountAccessAuthFactory::create([ + 'accountId' => $account['id'], + 'refreshToken' => EXPIRED_TOKEN, + 'clientIdentHash' => $clientIdentifikation->identificationHash, + ]); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Refresh token not found', function () { + $account = AccountFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + + $response = $this->app->handle($request); + $json = JsonFactory::create($response); + + $request = $this->createGetRequest( + '/api/token/refresh' + ) + ->withHeader('Authentication', $json['refreshToken']); + + $fluent = $this->getContainer()->get(Query::class); + + $fluent->delete('AccountAccessAuth')->where('accountId', $account['id'])->execute(); + + $response = $this->app->handle($request); + + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); diff --git a/tests/Integration/Factory/RequestPipingFactory.php b/tests/Integration/Factory/RequestPipingFactory.php new file mode 100644 index 00000000..dcfe1e8d --- /dev/null +++ b/tests/Integration/Factory/RequestPipingFactory.php @@ -0,0 +1,47 @@ + $middlewareClass Die Klasse der Middleware. + * @param ServerRequestInterface $originalRequest Der initiale Request. + * + * @return ServerRequestInterface Der Request mit den Attributen der Middleware. + */ + public static function process( + string $middlewareClass, + ServerRequestInterface $originalRequest + ): ServerRequestInterface { + $container = test()->getContainer(); + $middleware = $container->get($middlewareClass); + $dummyNextHandler = new class implements RequestHandlerInterface { + public ?ServerRequestInterface $savedRequest = null; + + public function handle(ServerRequestInterface $request): ResponseInterface + { + $this->savedRequest = $request; + return new EmptyResponse(HTTP::STATUS_NO_CONTENT); + } + }; + $middleware->process($originalRequest, $dummyNextHandler); + if ($dummyNextHandler->savedRequest === null) { + throw new RuntimeException( + 'Middleware did not call the next handler. Check if it returned an early response (e.g. 400).' + ); + } + + return $dummyNextHandler->savedRequest; + } +} diff --git a/tests/Integration/JsonFactory.php b/tests/Integration/JsonFactory.php new file mode 100644 index 00000000..1ed7b62f --- /dev/null +++ b/tests/Integration/JsonFactory.php @@ -0,0 +1,13 @@ +getBody(), true); + } +} diff --git a/tests/FunctionalTest/Mock/NullLogger.php b/tests/Integration/Mock/NullLogger.php similarity index 97% rename from tests/FunctionalTest/Mock/NullLogger.php rename to tests/Integration/Mock/NullLogger.php index ac8c5631..eb9fac3b 100644 --- a/tests/FunctionalTest/Mock/NullLogger.php +++ b/tests/Integration/Mock/NullLogger.php @@ -1,6 +1,6 @@ createGetRequest('/api/ping'); + + // 2. Request an die App übergeben (.handle() statt .run()) + $response = $this->app->handle($request); + + // 3. Status Code prüfen + expect($response->getStatusCode())->toBe(200); + + // 4. Body prüfen + $body = (string)$response->getBody(); + $data = json_decode($body, true); + + expect($data) + ->toBeArray() + ->toHaveKey('message', 'pong') + ->toHaveKey('ack'); +}); diff --git a/tests/Pest.php b/tests/Pest.php new file mode 100644 index 00000000..e85aaeca --- /dev/null +++ b/tests/Pest.php @@ -0,0 +1,137 @@ +beforeEach(function () { + /** @var PDO $pdo */ + $pdo = $this->container->get(PDO::class); + $pdo->beginTransaction(); +}) + ->afterEach(function () { + /** @var PDO $pdo */ + $pdo = $this->container->get(PDO::class); + if ($pdo->inTransaction()) { + $pdo->rollBack(); + } + }) + ->in('Integration'); + +/* +|-------------------------------------------------------------------------- +| Expectations +|-------------------------------------------------------------------------- +| +| When you're writing tests, you often need to check that values meet certain conditions. The +| "expect()" function gives you access to a set of "expectations" methods that you can use +| to assert different things. Of course, you may extend the Expectation API at any time. +| +*/ + +expect()->extend('toBeOne', function () { + return $this->toBe(1); +}); +expect()->extend('toHaveRecord', function (array $criteria) { + $container = test()->getContainer(); + + $fluent = $container->get(Query::class); + + $result = $fluent->from($this->value) + ->where($criteria) + ->fetch(); + + if ($result === false) { + throw new Exception( + sprintf( + "Failed to find a record in table '%s' matching criteria: %s", + $this->value, + json_encode($criteria) + ) + ); + } + return $this; +}); + +// Optional: Das Gegenteil (dontSeeInDatabase) +expect()->extend('toNotHaveRecord', function (array $criteria) { + $container = test()->getContainer(); + + $fluent = $container->get(Query::class); + + $result = $fluent->from($this->value)->where($criteria)->fetch(); + + if ($result !== false) { + throw new Exception( + sprintf( + "Found unexpected record in table '%s' matching criteria: %s", + $this->value, + json_encode($criteria) + ) + ); + } + return $this; +}); + +/* +|-------------------------------------------------------------------------- +| Functions +|-------------------------------------------------------------------------- +| +| While Pest is very powerful out-of-the-box, you may have some testing code specific to your +| project that you don't want to repeat in every file. Here you can also expose helpers as +| global functions to help you to reduce the number of lines of code in your test files. +| +*/ + +function something() +{ + // .. +} diff --git a/tests/TestIntegrationCase.php b/tests/TestIntegrationCase.php new file mode 100644 index 00000000..96dca63c --- /dev/null +++ b/tests/TestIntegrationCase.php @@ -0,0 +1,107 @@ +container = require __DIR__ . '/../config/container.php'; + + $this->app = $this->container->get(Application::class); + $factory = $this->container->get(MiddlewareFactory::class); + + (require __DIR__ . '/../config/pipeline.php')($this->app, $factory, $this->container); + + (require __DIR__ . '/../config/routes.php')($this->app, $factory, $this->container); + } + + public function getContainer(): ContainerInterface + { + // Singleton-Logik: Container nur einmal pro Testlauf laden, um Performance zu sparen + if ($this->container === null) { + // Pfad anpassen: Gehen Sie vom 'tests'-Ordner zurück ins Root-Verzeichnis + // Meistens liegt die container.php in config/container.php + $path = __DIR__ . '/../config/container.php'; + + if (!file_exists($path)) { + throw new RuntimeException("Container-Konfiguration nicht gefunden unter: $path"); + } + + $this->container = require $path; + } + + return $this->container; + } + + /** + * Hilfsmethode, um einen GET Request zu erstellen + */ + public function createGetRequest(string $path): ServerRequest + { + return (new ServerRequestFactory()) + ->createServerRequest('GET', new Uri($path)); + } + + /** + * Hilfsmethode, um einen POST Request mit JSON Body zu erstellen + */ + public function createJsonPostRequest(string $path, array $data): ServerRequest + { + $request = (new ServerRequestFactory()) + ->createServerRequest('POST', new Uri($path)) + ->withHeader('Content-Type', 'application/json'); + + $request->getBody()->write(json_encode($data)); + $request->getBody()->rewind(); + + return $request; + } + + public function insert(string $table, array $data): void + { + /** @var PDO $pdo */ + + $pdo = test()->container->get(PDO::class); + + $keys = array_keys($data); + $cols = implode(', ', $keys); + $placeholders = implode(', ', array_fill(0, count($keys), '?')); + + $sql = "INSERT INTO $table ($cols) VALUES ($placeholders)"; + $pdo->prepare($sql)->execute(array_values($data)); + } + /* + test('user can log in', function () + { + // Vorbereitung (Arrange) + insert('users', [ + 'email' => 'user@example.com', + 'password' => password_hash('secret', PASSWORD_DEFAULT), + ]); + + // Ausführung (Act) + $response = $this->app->handle(...); + + expect($response->getStatusCode())->toBe(200); + }); + */ +} diff --git a/tests/FunctionalTest/AbstractFunctional.php b/tests_backup/FunctionalTest/AbstractFunctional.php similarity index 100% rename from tests/FunctionalTest/AbstractFunctional.php rename to tests_backup/FunctionalTest/AbstractFunctional.php diff --git a/tests/FunctionalTest/Root/Account/AccessTokenHandlerTest.php b/tests_backup/FunctionalTest/Root/Account/AccessTokenHandlerTest.php similarity index 100% rename from tests/FunctionalTest/Root/Account/AccessTokenHandlerTest.php rename to tests_backup/FunctionalTest/Root/Account/AccessTokenHandlerTest.php diff --git a/tests/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php b/tests_backup/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php similarity index 100% rename from tests/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php rename to tests_backup/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php diff --git a/tests/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php b/tests_backup/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php similarity index 100% rename from tests/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php rename to tests_backup/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php diff --git a/tests/FunctionalTest/Root/PingHandlerTest.php b/tests_backup/FunctionalTest/Root/PingHandlerTest.php similarity index 100% rename from tests/FunctionalTest/Root/PingHandlerTest.php rename to tests_backup/FunctionalTest/Root/PingHandlerTest.php diff --git a/tests/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php b/tests_backup/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php similarity index 100% rename from tests/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php rename to tests_backup/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php diff --git a/tests/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php b/tests_backup/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php similarity index 100% rename from tests/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php rename to tests_backup/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php diff --git a/tests/FunctionalTest/bootstrap.php b/tests_backup/FunctionalTest/bootstrap.php similarity index 100% rename from tests/FunctionalTest/bootstrap.php rename to tests_backup/FunctionalTest/bootstrap.php diff --git a/tests/FunctionalTest/database/migrations/Version20990921210156_InsertAccountTestData.php b/tests_backup/FunctionalTest/database/migrations/Version20990921210156_InsertAccountTestData.php similarity index 100% rename from tests/FunctionalTest/database/migrations/Version20990921210156_InsertAccountTestData.php rename to tests_backup/FunctionalTest/database/migrations/Version20990921210156_InsertAccountTestData.php diff --git a/tests/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php b/tests_backup/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php similarity index 100% rename from tests/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php rename to tests_backup/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php diff --git a/tests/UnitTest/AppTest/Handler/AbstractTestHandler.php b/tests_backup/UnitTest/AppTest/Handler/AbstractTestHandler.php similarity index 100% rename from tests/UnitTest/AppTest/Handler/AbstractTestHandler.php rename to tests_backup/UnitTest/AppTest/Handler/AbstractTestHandler.php diff --git a/tests/UnitTest/AppTest/Handler/PingHandlerTest.php b/tests_backup/UnitTest/AppTest/Handler/PingHandlerTest.php similarity index 100% rename from tests/UnitTest/AppTest/Handler/PingHandlerTest.php rename to tests_backup/UnitTest/AppTest/Handler/PingHandlerTest.php diff --git a/tests/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php b/tests_backup/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php similarity index 100% rename from tests/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php rename to tests_backup/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php diff --git a/tests/UnitTest/AppTest/Hydrator/AccountHydratorTest.php b/tests_backup/UnitTest/AppTest/Hydrator/AccountHydratorTest.php similarity index 100% rename from tests/UnitTest/AppTest/Hydrator/AccountHydratorTest.php rename to tests_backup/UnitTest/AppTest/Hydrator/AccountHydratorTest.php diff --git a/tests/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php b/tests_backup/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php similarity index 100% rename from tests/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php rename to tests_backup/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php diff --git a/tests/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php similarity index 100% rename from tests/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php rename to tests_backup/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php diff --git a/tests/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php similarity index 99% rename from tests/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php rename to tests_backup/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php index 286b2176..cdc893be 100644 --- a/tests/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php +++ b/tests_backup/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php @@ -8,10 +8,10 @@ use Exdrals\Shared\Infrastructure\Persistence\Repository\Account\AccountRepositoryInterface; use Exdrals\Shared\Utils\UuidFactory; use Exdrals\Shared\Utils\UuidFactoryInterface; -use FunctionalTest\Mock\NullLogger; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; +use Tests\Integration\Mock\NullLogger; use UnitTest\Mock\Constants\Account; use UnitTest\Mock\MockAccountAuthenticationMiddlewareRequestHandler; use UnitTest\Mock\Repository\MockAccountRepository; diff --git a/tests/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php similarity index 100% rename from tests/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php rename to tests_backup/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php diff --git a/tests/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php similarity index 100% rename from tests/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php rename to tests_backup/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php diff --git a/tests/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php similarity index 100% rename from tests/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php rename to tests_backup/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php diff --git a/tests/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php similarity index 100% rename from tests/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php rename to tests_backup/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php diff --git a/tests/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php similarity index 100% rename from tests/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php rename to tests_backup/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php diff --git a/tests/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php b/tests_backup/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php similarity index 100% rename from tests/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php rename to tests_backup/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php diff --git a/tests/UnitTest/AppTest/Repository/AccountRepositoryTest.php b/tests_backup/UnitTest/AppTest/Repository/AccountRepositoryTest.php similarity index 100% rename from tests/UnitTest/AppTest/Repository/AccountRepositoryTest.php rename to tests_backup/UnitTest/AppTest/Repository/AccountRepositoryTest.php diff --git a/tests/UnitTest/AppTest/Service/AccessTokenServiceTest.php b/tests_backup/UnitTest/AppTest/Service/AccessTokenServiceTest.php similarity index 100% rename from tests/UnitTest/AppTest/Service/AccessTokenServiceTest.php rename to tests_backup/UnitTest/AppTest/Service/AccessTokenServiceTest.php diff --git a/tests/UnitTest/AppTest/Service/AuthenticationServiceTest.php b/tests_backup/UnitTest/AppTest/Service/AuthenticationServiceTest.php similarity index 100% rename from tests/UnitTest/AppTest/Service/AuthenticationServiceTest.php rename to tests_backup/UnitTest/AppTest/Service/AuthenticationServiceTest.php diff --git a/tests/UnitTest/AppTest/Service/RefreshTokenServiceTest.php b/tests_backup/UnitTest/AppTest/Service/RefreshTokenServiceTest.php similarity index 100% rename from tests/UnitTest/AppTest/Service/RefreshTokenServiceTest.php rename to tests_backup/UnitTest/AppTest/Service/RefreshTokenServiceTest.php diff --git a/tests/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php b/tests_backup/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php similarity index 100% rename from tests/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php rename to tests_backup/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php diff --git a/tests/UnitTest/AppTest/Table/AccountTableTest.php b/tests_backup/UnitTest/AppTest/Table/AccountTableTest.php similarity index 100% rename from tests/UnitTest/AppTest/Table/AccountTableTest.php rename to tests_backup/UnitTest/AppTest/Table/AccountTableTest.php diff --git a/tests/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php b/tests_backup/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php similarity index 100% rename from tests/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php rename to tests_backup/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php diff --git a/tests/UnitTest/CoreTest/Factory/QueryFactoryTest.php b/tests_backup/UnitTest/CoreTest/Factory/QueryFactoryTest.php similarity index 100% rename from tests/UnitTest/CoreTest/Factory/QueryFactoryTest.php rename to tests_backup/UnitTest/CoreTest/Factory/QueryFactoryTest.php diff --git a/tests/UnitTest/JsonRequestHelper.php b/tests_backup/UnitTest/JsonRequestHelper.php similarity index 100% rename from tests/UnitTest/JsonRequestHelper.php rename to tests_backup/UnitTest/JsonRequestHelper.php diff --git a/tests/UnitTest/Mock/Constants/Account.php b/tests_backup/UnitTest/Mock/Constants/Account.php similarity index 100% rename from tests/UnitTest/Mock/Constants/Account.php rename to tests_backup/UnitTest/Mock/Constants/Account.php diff --git a/tests/UnitTest/Mock/Constants/AccountAccessAuth.php b/tests_backup/UnitTest/Mock/Constants/AccountAccessAuth.php similarity index 100% rename from tests/UnitTest/Mock/Constants/AccountAccessAuth.php rename to tests_backup/UnitTest/Mock/Constants/AccountAccessAuth.php diff --git a/tests/UnitTest/Mock/Constants/Token.php b/tests_backup/UnitTest/Mock/Constants/Token.php similarity index 100% rename from tests/UnitTest/Mock/Constants/Token.php rename to tests_backup/UnitTest/Mock/Constants/Token.php diff --git a/tests/UnitTest/Mock/Database/MockDelete.php b/tests_backup/UnitTest/Mock/Database/MockDelete.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockDelete.php rename to tests_backup/UnitTest/Mock/Database/MockDelete.php diff --git a/tests/UnitTest/Mock/Database/MockDeleteFailed.php b/tests_backup/UnitTest/Mock/Database/MockDeleteFailed.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockDeleteFailed.php rename to tests_backup/UnitTest/Mock/Database/MockDeleteFailed.php diff --git a/tests/UnitTest/Mock/Database/MockInsert.php b/tests_backup/UnitTest/Mock/Database/MockInsert.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockInsert.php rename to tests_backup/UnitTest/Mock/Database/MockInsert.php diff --git a/tests/UnitTest/Mock/Database/MockInsertFailed.php b/tests_backup/UnitTest/Mock/Database/MockInsertFailed.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockInsertFailed.php rename to tests_backup/UnitTest/Mock/Database/MockInsertFailed.php diff --git a/tests/UnitTest/Mock/Database/MockPDO.php b/tests_backup/UnitTest/Mock/Database/MockPDO.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockPDO.php rename to tests_backup/UnitTest/Mock/Database/MockPDO.php diff --git a/tests/UnitTest/Mock/Database/MockQuery.php b/tests_backup/UnitTest/Mock/Database/MockQuery.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockQuery.php rename to tests_backup/UnitTest/Mock/Database/MockQuery.php diff --git a/tests/UnitTest/Mock/Database/MockQueryFailed.php b/tests_backup/UnitTest/Mock/Database/MockQueryFailed.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockQueryFailed.php rename to tests_backup/UnitTest/Mock/Database/MockQueryFailed.php diff --git a/tests/UnitTest/Mock/Database/MockSelect.php b/tests_backup/UnitTest/Mock/Database/MockSelect.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockSelect.php rename to tests_backup/UnitTest/Mock/Database/MockSelect.php diff --git a/tests/UnitTest/Mock/Database/MockSelectFailed.php b/tests_backup/UnitTest/Mock/Database/MockSelectFailed.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockSelectFailed.php rename to tests_backup/UnitTest/Mock/Database/MockSelectFailed.php diff --git a/tests/UnitTest/Mock/Database/MockUpdate.php b/tests_backup/UnitTest/Mock/Database/MockUpdate.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockUpdate.php rename to tests_backup/UnitTest/Mock/Database/MockUpdate.php diff --git a/tests/UnitTest/Mock/Database/MockUpdateFailed.php b/tests_backup/UnitTest/Mock/Database/MockUpdateFailed.php similarity index 100% rename from tests/UnitTest/Mock/Database/MockUpdateFailed.php rename to tests_backup/UnitTest/Mock/Database/MockUpdateFailed.php diff --git a/tests/UnitTest/Mock/Entity/MockAccount.php b/tests_backup/UnitTest/Mock/Entity/MockAccount.php similarity index 100% rename from tests/UnitTest/Mock/Entity/MockAccount.php rename to tests_backup/UnitTest/Mock/Entity/MockAccount.php diff --git a/tests/UnitTest/Mock/MockAccountAuthenticationMiddlewareRequestHandler.php b/tests_backup/UnitTest/Mock/MockAccountAuthenticationMiddlewareRequestHandler.php similarity index 100% rename from tests/UnitTest/Mock/MockAccountAuthenticationMiddlewareRequestHandler.php rename to tests_backup/UnitTest/Mock/MockAccountAuthenticationMiddlewareRequestHandler.php diff --git a/tests/UnitTest/Mock/MockContainer.php b/tests_backup/UnitTest/Mock/MockContainer.php similarity index 100% rename from tests/UnitTest/Mock/MockContainer.php rename to tests_backup/UnitTest/Mock/MockContainer.php diff --git a/tests/UnitTest/Mock/MockRequestHandler.php b/tests_backup/UnitTest/Mock/MockRequestHandler.php similarity index 100% rename from tests/UnitTest/Mock/MockRequestHandler.php rename to tests_backup/UnitTest/Mock/MockRequestHandler.php diff --git a/tests/UnitTest/Mock/MockResponse.php b/tests_backup/UnitTest/Mock/MockResponse.php similarity index 100% rename from tests/UnitTest/Mock/MockResponse.php rename to tests_backup/UnitTest/Mock/MockResponse.php diff --git a/tests/UnitTest/Mock/MockServerRequest.php b/tests_backup/UnitTest/Mock/MockServerRequest.php similarity index 100% rename from tests/UnitTest/Mock/MockServerRequest.php rename to tests_backup/UnitTest/Mock/MockServerRequest.php diff --git a/tests/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php b/tests_backup/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php similarity index 100% rename from tests/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php rename to tests_backup/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php diff --git a/tests/UnitTest/Mock/Repository/MockAccountRepository.php b/tests_backup/UnitTest/Mock/Repository/MockAccountRepository.php similarity index 100% rename from tests/UnitTest/Mock/Repository/MockAccountRepository.php rename to tests_backup/UnitTest/Mock/Repository/MockAccountRepository.php diff --git a/tests/UnitTest/Mock/Repository/MockAccountRepositoryAccountAuthenticationMiddlewareInvalidToken.php b/tests_backup/UnitTest/Mock/Repository/MockAccountRepositoryAccountAuthenticationMiddlewareInvalidToken.php similarity index 100% rename from tests/UnitTest/Mock/Repository/MockAccountRepositoryAccountAuthenticationMiddlewareInvalidToken.php rename to tests_backup/UnitTest/Mock/Repository/MockAccountRepositoryAccountAuthenticationMiddlewareInvalidToken.php diff --git a/tests/UnitTest/Mock/Service/MockAccessTokenService.php b/tests_backup/UnitTest/Mock/Service/MockAccessTokenService.php similarity index 100% rename from tests/UnitTest/Mock/Service/MockAccessTokenService.php rename to tests_backup/UnitTest/Mock/Service/MockAccessTokenService.php diff --git a/tests/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php b/tests_backup/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php similarity index 100% rename from tests/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php rename to tests_backup/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php diff --git a/tests/UnitTest/Mock/Service/MockAuthenticationService.php b/tests_backup/UnitTest/Mock/Service/MockAuthenticationService.php similarity index 100% rename from tests/UnitTest/Mock/Service/MockAuthenticationService.php rename to tests_backup/UnitTest/Mock/Service/MockAuthenticationService.php diff --git a/tests/UnitTest/Mock/Service/MockClientIdentificationService.php b/tests_backup/UnitTest/Mock/Service/MockClientIdentificationService.php similarity index 100% rename from tests/UnitTest/Mock/Service/MockClientIdentificationService.php rename to tests_backup/UnitTest/Mock/Service/MockClientIdentificationService.php diff --git a/tests/UnitTest/Mock/Service/MockRefreshTokenService.php b/tests_backup/UnitTest/Mock/Service/MockRefreshTokenService.php similarity index 100% rename from tests/UnitTest/Mock/Service/MockRefreshTokenService.php rename to tests_backup/UnitTest/Mock/Service/MockRefreshTokenService.php diff --git a/tests/UnitTest/Mock/Table/MockAccountAccessAuthTable.php b/tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTable.php similarity index 100% rename from tests/UnitTest/Mock/Table/MockAccountAccessAuthTable.php rename to tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTable.php diff --git a/tests/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php b/tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php similarity index 100% rename from tests/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php rename to tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php diff --git a/tests/UnitTest/Mock/Table/MockAccountTable.php b/tests_backup/UnitTest/Mock/Table/MockAccountTable.php similarity index 100% rename from tests/UnitTest/Mock/Table/MockAccountTable.php rename to tests_backup/UnitTest/Mock/Table/MockAccountTable.php diff --git a/tests/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php b/tests_backup/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php similarity index 100% rename from tests/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php rename to tests_backup/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php diff --git a/tests/UnitTest/Mock/Table/MockAccountTableFailed.php b/tests_backup/UnitTest/Mock/Table/MockAccountTableFailed.php similarity index 100% rename from tests/UnitTest/Mock/Table/MockAccountTableFailed.php rename to tests_backup/UnitTest/Mock/Table/MockAccountTableFailed.php diff --git a/tests/UnitTest/Mock/Validator/MockAuthenticationValidator.php b/tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidator.php similarity index 100% rename from tests/UnitTest/Mock/Validator/MockAuthenticationValidator.php rename to tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidator.php diff --git a/tests/UnitTest/Mock/Validator/MockAuthenticationValidatorFailed.php b/tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidatorFailed.php similarity index 100% rename from tests/UnitTest/Mock/Validator/MockAuthenticationValidatorFailed.php rename to tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidatorFailed.php From 9050c9bac46d26b5c72c0b51ff20756178ed91fe Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 16:48:33 +0100 Subject: [PATCH 02/17] fix: change pest for github action --- tests/Pest.php | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/Pest.php b/tests/Pest.php index e85aaeca..230728ea 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -17,25 +17,38 @@ (function () { putenv('APP_ENV=testing'); $_ENV['APP_ENV'] = 'testing'; + + $dbHost = getenv('DB_HOST') ?: (getenv('GITHUB_ACTIONS') ? '127.0.0.1' : 'database-testing'); + $dbPort = (int)(getenv('DB_PORT') ?: 3306); + fwrite(STDOUT, "\n[Docker-Setup] Warte auf database-testing...\n"); $bin = __DIR__ . '/../bin/migrations.php'; - $maxTries = 10; + if (!file_exists($bin)) { + fwrite(STDERR, "[Error] Migrations-Binärdatei nicht gefunden unter: $bin\n"); + exit(1); + } + $maxTries = 15; $wait = 1; // Sekunde - // Versuche eine Verbindung aufzubauen, bevor die Migrationen starten - // (Verhindert Absturz, falls DB noch am Booten ist) + // 2. Verbindungs-Check + $connected = false; for ($i = 0; $i < $maxTries; $i++) { - // Wir prüfen einfach, ob wir den Port erreichen können - $fp = @fsockopen('database-testing', 3306, $errno, $errstr, 2); + $fp = @fsockopen($dbHost, $dbPort, $errno, $errstr, 2); if ($fp) { fclose($fp); + $connected = true; break; } fwrite(STDOUT, '.'); sleep($wait); } + if (!$connected) { + fwrite(STDERR, "\n[Error] Datenbank $dbHost ist nicht erreichbar!\n"); + exit(1); + } + fwrite(STDOUT, "\n[Docker-Setup] Starte Migrationen...\n"); // WICHTIG: Nutze im Befehl den Pfad innerhalb des Containers From 507f80b4a549c276ba0c514c2a2e8149ebc417e8 Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 16:58:35 +0100 Subject: [PATCH 03/17] fix: change pest for github action --- tests/Pest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/Pest.php b/tests/Pest.php index 230728ea..8fbb5ebb 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -15,8 +15,10 @@ */ (function () { - putenv('APP_ENV=testing'); - $_ENV['APP_ENV'] = 'testing'; + if (!getenv('APP_ENV')) { + putenv('APP_ENV=testing'); + $_ENV['APP_ENV'] = 'testing'; + } $dbHost = getenv('DB_HOST') ?: (getenv('GITHUB_ACTIONS') ? '127.0.0.1' : 'database-testing'); $dbPort = (int)(getenv('DB_PORT') ?: 3306); From 4d4463792c4e87c0166446fd5b0448325240e185 Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 17:02:46 +0100 Subject: [PATCH 04/17] fix: change pest for github action --- .github/workflows/codestyle-and-unittest.yml | 2 +- config/autoload/migrations.action.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/codestyle-and-unittest.yml b/.github/workflows/codestyle-and-unittest.yml index 921472f3..d05f3c68 100644 --- a/.github/workflows/codestyle-and-unittest.yml +++ b/.github/workflows/codestyle-and-unittest.yml @@ -77,7 +77,7 @@ jobs: uses: rjstone/discord-webhook-notify@v1.0.4 with: severity: error - details: Unit or Functional Tests failed. + details: Integration Tests failed. webhookUrl: ${{ secrets.WEBHOOK_DISCORD_URL }} # 3. Job: Abschluss-Benachrichtigung diff --git a/config/autoload/migrations.action.php b/config/autoload/migrations.action.php index 166dbab1..0626d103 100644 --- a/config/autoload/migrations.action.php +++ b/config/autoload/migrations.action.php @@ -12,7 +12,6 @@ 'migrations_paths' => [ 'Migrations' => __DIR__ . '/../../database/migrations', - 'TestDataMigrations' => __DIR__ . '/../../tests/FunctionalTest/database/migrations', ], 'all_or_nothing' => true, From a8373d0e6917f3d40b54423401aee223270a0012 Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 17:10:09 +0100 Subject: [PATCH 05/17] fix: change pest for github action --- .github/workflows/codestyle-and-unittest.yml | 2 +- tests/Pest.php | 31 ++++++++------------ 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/.github/workflows/codestyle-and-unittest.yml b/.github/workflows/codestyle-and-unittest.yml index d05f3c68..8a5dc475 100644 --- a/.github/workflows/codestyle-and-unittest.yml +++ b/.github/workflows/codestyle-and-unittest.yml @@ -70,7 +70,7 @@ jobs: uses: ./.github/actions/setup-php-composer - name: Run PHP Integration Test - run: composer run-script pest + run: ./vendor/bin/pest --configuration phpunit.xml --compact - name: Notify Failure if: failure() diff --git a/tests/Pest.php b/tests/Pest.php index 8fbb5ebb..43822e92 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -15,25 +15,21 @@ */ (function () { - if (!getenv('APP_ENV')) { - putenv('APP_ENV=testing'); - $_ENV['APP_ENV'] = 'testing'; - } + // 1. APP_ENV Logik: Priorität für GHA (action) + $appEnv = getenv('APP_ENV') ?: 'testing'; + putenv("APP_ENV=$appEnv"); + $_ENV['APP_ENV'] = $appEnv; + // 2. DB Host Erkennung $dbHost = getenv('DB_HOST') ?: (getenv('GITHUB_ACTIONS') ? '127.0.0.1' : 'database-testing'); $dbPort = (int)(getenv('DB_PORT') ?: 3306); - fwrite(STDOUT, "\n[Docker-Setup] Warte auf database-testing...\n"); + fwrite(STDOUT, "\n[Setup-Neu] Nutze Umgebung: $appEnv\n"); + fwrite(STDOUT, "[Setup-Neu] Warte auf Datenbank $dbHost:$dbPort...\n"); $bin = __DIR__ . '/../bin/migrations.php'; - if (!file_exists($bin)) { - fwrite(STDERR, "[Error] Migrations-Binärdatei nicht gefunden unter: $bin\n"); - exit(1); - } - $maxTries = 15; - $wait = 1; // Sekunde + $maxTries = 20; // Mehr Puffer für GHA - // 2. Verbindungs-Check $connected = false; for ($i = 0; $i < $maxTries; $i++) { $fp = @fsockopen($dbHost, $dbPort, $errno, $errstr, 2); @@ -43,27 +39,24 @@ break; } fwrite(STDOUT, '.'); - sleep($wait); + sleep(1); } if (!$connected) { - fwrite(STDERR, "\n[Error] Datenbank $dbHost ist nicht erreichbar!\n"); + fwrite(STDERR, "\n[Error] Datenbank nicht erreichbar!\n"); exit(1); } - fwrite(STDOUT, "\n[Docker-Setup] Starte Migrationen...\n"); + fwrite(STDOUT, "\n[Setup-Neu] Migrationen starten...\n"); - // WICHTIG: Nutze im Befehl den Pfad innerhalb des Containers $resultCode = 0; passthru("php $bin migrations:migrate --no-interaction --quiet first", $resultCode); passthru("php $bin migrations:migrate --no-interaction --quiet", $resultCode); if ($resultCode !== 0) { - fwrite(STDERR, "[Error] Migrationen im Docker-Netzwerk fehlgeschlagen!\n"); exit($resultCode); } - - fwrite(STDOUT, "[Docker-Setup] Datenbank bereit.\n\n"); + fwrite(STDOUT, "[Setup-Neu] Datenbank bereit.\n\n"); })(); uses(TestIntegrationCase::class)->beforeEach(function () { From ea00211e0399f60aa5a1d7f6684cfd527be7c5e0 Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 17:15:37 +0100 Subject: [PATCH 06/17] fix: change pest for github action --- .github/workflows/codestyle-and-unittest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codestyle-and-unittest.yml b/.github/workflows/codestyle-and-unittest.yml index 8a5dc475..ea3f5722 100644 --- a/.github/workflows/codestyle-and-unittest.yml +++ b/.github/workflows/codestyle-and-unittest.yml @@ -70,7 +70,7 @@ jobs: uses: ./.github/actions/setup-php-composer - name: Run PHP Integration Test - run: ./vendor/bin/pest --configuration phpunit.xml --compact + run: ./vendor/bin/pest --compact - name: Notify Failure if: failure() From 8b0528504986f69f2533fdb134a7466208594d97 Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 17:44:23 +0100 Subject: [PATCH 07/17] fix: change pest for github action --- .github/workflows/codestyle-and-unittest.yml | 13 +++++- composer.json | 7 ++- tests/Pest.php | 49 ++------------------ tests/setup-db.php | 46 ++++++++++++++++++ 4 files changed, 67 insertions(+), 48 deletions(-) create mode 100644 tests/setup-db.php diff --git a/.github/workflows/codestyle-and-unittest.yml b/.github/workflows/codestyle-and-unittest.yml index ea3f5722..77332cb7 100644 --- a/.github/workflows/codestyle-and-unittest.yml +++ b/.github/workflows/codestyle-and-unittest.yml @@ -69,8 +69,17 @@ jobs: - name: Setup PHP and Composer uses: ./.github/actions/setup-php-composer - - name: Run PHP Integration Test - run: ./vendor/bin/pest --compact + - name: setting up database + run: php tests/setup-db.php + env: + APP_ENV: action + DB_HOST: 127.0.0.1 + + - name: Run Tests + run: ./vendor/bin/pest --configuration=phpunit.xml --compact + env: + APP_ENV: action + DB_HOST: 127.0.0.1 - name: Notify Failure if: failure() diff --git a/composer.json b/composer.json index ccf6107f..3a9b9990 100644 --- a/composer.json +++ b/composer.json @@ -118,10 +118,15 @@ "phpcs": "phpcs --standard=phpcs.xml -s -p", "phplint": "vendor/bin/phplint", "phpstan": "vendor/bin/phpstan analyse -c phpstan.neon", - "pest": "vendor/bin/pest", + "pest-setup": "php ./test/setup-db.php", + "pest-run": "vendor/bin/pest", "post-create-project-cmd": [ "@development-enable" ], + "pest": [ + "@pest-setup", + "@pest-run" + ], "test": [ "@pest" ], diff --git a/tests/Pest.php b/tests/Pest.php index 43822e92..c7ed5a9b 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -13,51 +13,10 @@ | need to change it using the "uses()" function to bind a different classes or traits. | */ - -(function () { - // 1. APP_ENV Logik: Priorität für GHA (action) - $appEnv = getenv('APP_ENV') ?: 'testing'; - putenv("APP_ENV=$appEnv"); - $_ENV['APP_ENV'] = $appEnv; - - // 2. DB Host Erkennung - $dbHost = getenv('DB_HOST') ?: (getenv('GITHUB_ACTIONS') ? '127.0.0.1' : 'database-testing'); - $dbPort = (int)(getenv('DB_PORT') ?: 3306); - - fwrite(STDOUT, "\n[Setup-Neu] Nutze Umgebung: $appEnv\n"); - fwrite(STDOUT, "[Setup-Neu] Warte auf Datenbank $dbHost:$dbPort...\n"); - - $bin = __DIR__ . '/../bin/migrations.php'; - $maxTries = 20; // Mehr Puffer für GHA - - $connected = false; - for ($i = 0; $i < $maxTries; $i++) { - $fp = @fsockopen($dbHost, $dbPort, $errno, $errstr, 2); - if ($fp) { - fclose($fp); - $connected = true; - break; - } - fwrite(STDOUT, '.'); - sleep(1); - } - - if (!$connected) { - fwrite(STDERR, "\n[Error] Datenbank nicht erreichbar!\n"); - exit(1); - } - - fwrite(STDOUT, "\n[Setup-Neu] Migrationen starten...\n"); - - $resultCode = 0; - passthru("php $bin migrations:migrate --no-interaction --quiet first", $resultCode); - passthru("php $bin migrations:migrate --no-interaction --quiet", $resultCode); - - if ($resultCode !== 0) { - exit($resultCode); - } - fwrite(STDOUT, "[Setup-Neu] Datenbank bereit.\n\n"); -})(); +// 1. APP_ENV Logik: Priorität für GHA (action) +$appEnv = getenv('APP_ENV') ?: 'testing'; +putenv("APP_ENV=$appEnv"); +$_ENV['APP_ENV'] = $appEnv; uses(TestIntegrationCase::class)->beforeEach(function () { /** @var PDO $pdo */ diff --git a/tests/setup-db.php b/tests/setup-db.php new file mode 100644 index 00000000..4f76c724 --- /dev/null +++ b/tests/setup-db.php @@ -0,0 +1,46 @@ + Date: Mon, 2 Feb 2026 17:48:32 +0100 Subject: [PATCH 08/17] fix: change pest for github action --- .gitignore | 1 - phpunit.xml | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 phpunit.xml diff --git a/.gitignore b/.gitignore index e3d8f26f..ceeb623f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,6 @@ coverage.xml /.phpunit.result.cache /clover.xml /coveralls-upload.json -/phpunit.xml /public/test.php /tmp .env diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 00000000..a421e432 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,28 @@ + + + + + + + + ./tests + + + + + ./app + ./src + + + + + + + + + From 6e76d81961204fbca5b1615bcd43741f2324885a Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 17:56:35 +0100 Subject: [PATCH 09/17] fix: change pest for github action --- composer.json | 7 +--- config/autoload/dependencies.action.php | 6 ++-- config/config.php | 2 +- tests/Pest.php | 45 +++++++++++++++++++++++++ tests/setup-db.php | 43 ----------------------- 5 files changed, 50 insertions(+), 53 deletions(-) diff --git a/composer.json b/composer.json index 3a9b9990..ccf6107f 100644 --- a/composer.json +++ b/composer.json @@ -118,15 +118,10 @@ "phpcs": "phpcs --standard=phpcs.xml -s -p", "phplint": "vendor/bin/phplint", "phpstan": "vendor/bin/phpstan analyse -c phpstan.neon", - "pest-setup": "php ./test/setup-db.php", - "pest-run": "vendor/bin/pest", + "pest": "vendor/bin/pest", "post-create-project-cmd": [ "@development-enable" ], - "pest": [ - "@pest-setup", - "@pest-run" - ], "test": [ "@pest" ], diff --git a/config/autoload/dependencies.action.php b/config/autoload/dependencies.action.php index 9899a342..0bbb4e72 100644 --- a/config/autoload/dependencies.action.php +++ b/config/autoload/dependencies.action.php @@ -1,11 +1,11 @@ [ @@ -21,7 +21,7 @@ 'factories' => [ 'database' => DatabaseFactory::class, 'query' => QueryFactory::class, - 'logger' => LoggerFactory::class, + 'logger' => NullLoggerFactory::class, 'uuid' => UuidFactory::class, 'mailer' => NullMailerFactory::class, ], diff --git a/config/config.php b/config/config.php index b7bb7b0a..d3216a54 100644 --- a/config/config.php +++ b/config/config.php @@ -44,7 +44,7 @@ class_exists(\Mezzio\Swoole\ConfigProvider::class) // - `*.local.php` new PhpFileProvider( realpath(__DIR__) . sprintf( - '/autoload/{,*.}{global,local,%s}.php', + '/autoload/{,*.}{global,%s,local}.php', getenv('APP_ENV') ?: 'production' ) ), diff --git a/tests/Pest.php b/tests/Pest.php index c7ed5a9b..249e3332 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -18,6 +18,51 @@ putenv("APP_ENV=$appEnv"); $_ENV['APP_ENV'] = $appEnv; +(function () { + // 1. APP_ENV Logik: Priorität für GHA (action) + $appEnv = getenv('APP_ENV') ?: 'testing'; + putenv("APP_ENV=$appEnv"); + $_ENV['APP_ENV'] = $appEnv; + + // 2. DB Host Erkennung + $dbHost = getenv('DB_HOST') ?: (getenv('GITHUB_ACTIONS') ? '127.0.0.1' : 'database-testing'); + $dbPort = (int)(getenv('DB_PORT') ?: 3306); + + fwrite(STDOUT, "\n[Setup-Neu] Nutze Umgebung: $appEnv\n"); + fwrite(STDOUT, "[Setup-Neu] Warte auf Datenbank $dbHost:$dbPort...\n"); + + $bin = __DIR__ . '/../bin/migrations.php'; + $maxTries = 20; // Mehr Puffer für GHA + + $connected = false; + for ($i = 0; $i < $maxTries; $i++) { + $fp = @fsockopen($dbHost, $dbPort, $errno, $errstr, 2); + if ($fp) { + fclose($fp); + $connected = true; + break; + } + fwrite(STDOUT, '.'); + sleep(1); + } + + if (!$connected) { + fwrite(STDERR, "\n[Error] Datenbank nicht erreichbar!\n"); + exit(1); + } + + fwrite(STDOUT, "\n[Setup-Neu] Migrationen starten...\n"); + + $resultCode = 0; + passthru("php $bin migrations:migrate --no-interaction --quiet first", $resultCode); + passthru("php $bin migrations:migrate --no-interaction --quiet", $resultCode); + + if ($resultCode !== 0) { + exit($resultCode); + } + fwrite(STDOUT, "[Setup-Neu] Datenbank bereit.\n\n"); +})(); + uses(TestIntegrationCase::class)->beforeEach(function () { /** @var PDO $pdo */ $pdo = $this->container->get(PDO::class); diff --git a/tests/setup-db.php b/tests/setup-db.php index 4f76c724..6a1ec61e 100644 --- a/tests/setup-db.php +++ b/tests/setup-db.php @@ -1,46 +1,3 @@ Date: Mon, 2 Feb 2026 18:01:47 +0100 Subject: [PATCH 10/17] fix: change pest for github action --- tests/Pest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Pest.php b/tests/Pest.php index 249e3332..7576767f 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -28,8 +28,8 @@ $dbHost = getenv('DB_HOST') ?: (getenv('GITHUB_ACTIONS') ? '127.0.0.1' : 'database-testing'); $dbPort = (int)(getenv('DB_PORT') ?: 3306); - fwrite(STDOUT, "\n[Setup-Neu] Nutze Umgebung: $appEnv\n"); - fwrite(STDOUT, "[Setup-Neu] Warte auf Datenbank $dbHost:$dbPort...\n"); + fwrite(STDOUT, "\n[Setup] Environment: $appEnv\n"); + fwrite(STDOUT, "[Setup] Waiting for database $dbHost:$dbPort...\n"); $bin = __DIR__ . '/../bin/migrations.php'; $maxTries = 20; // Mehr Puffer für GHA @@ -47,11 +47,11 @@ } if (!$connected) { - fwrite(STDERR, "\n[Error] Datenbank nicht erreichbar!\n"); + fwrite(STDERR, "\n[Error] Database not accessible!\n"); exit(1); } - fwrite(STDOUT, "\n[Setup-Neu] Migrationen starten...\n"); + fwrite(STDOUT, "[Setup] Start migrations...\n"); $resultCode = 0; passthru("php $bin migrations:migrate --no-interaction --quiet first", $resultCode); @@ -60,7 +60,7 @@ if ($resultCode !== 0) { exit($resultCode); } - fwrite(STDOUT, "[Setup-Neu] Datenbank bereit.\n\n"); + fwrite(STDOUT, "[Setup] Database ready.\n\n"); })(); uses(TestIntegrationCase::class)->beforeEach(function () { From e783f1daf769af694a5965765865af2ae8c4bce4 Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Mon, 2 Feb 2026 18:10:44 +0100 Subject: [PATCH 11/17] fix: change pest for github action --- .github/workflows/codestyle-and-unittest.yml | 8 +------- tests/setup-db.php | 3 --- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 tests/setup-db.php diff --git a/.github/workflows/codestyle-and-unittest.yml b/.github/workflows/codestyle-and-unittest.yml index 77332cb7..241dddb4 100644 --- a/.github/workflows/codestyle-and-unittest.yml +++ b/.github/workflows/codestyle-and-unittest.yml @@ -69,12 +69,6 @@ jobs: - name: Setup PHP and Composer uses: ./.github/actions/setup-php-composer - - name: setting up database - run: php tests/setup-db.php - env: - APP_ENV: action - DB_HOST: 127.0.0.1 - - name: Run Tests run: ./vendor/bin/pest --configuration=phpunit.xml --compact env: @@ -92,7 +86,7 @@ jobs: # 3. Job: Abschluss-Benachrichtigung final-status: name: Final Status Message - needs: [static-analysis, tests] + needs: [ static-analysis, tests ] if: always() runs-on: ubuntu-latest steps: diff --git a/tests/setup-db.php b/tests/setup-db.php deleted file mode 100644 index 6a1ec61e..00000000 --- a/tests/setup-db.php +++ /dev/null @@ -1,3 +0,0 @@ - Date: Mon, 2 Feb 2026 22:52:48 +0100 Subject: [PATCH 12/17] fix: enable detailed output for incomplete tests in PHPUnit configuration --- phpunit.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpunit.xml b/phpunit.xml index a421e432..06552fe4 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -4,6 +4,7 @@ bootstrap="vendor/autoload.php" colors="true" cacheDirectory=".phpunit.cache" + displayDetailsOnIncompleteTests="true" > From 3a45207821182071c5def085addf00e08698d2dc Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Tue, 3 Feb 2026 00:29:58 +0100 Subject: [PATCH 13/17] test: add integration tests for password forgotten flow --- .../Account/Identity/src/ConfigProvider.php | 2 +- .../AccountPasswordForgottenHandler.php | 2 +- .../Service/Account/PasswordService.php | 2 - .../Identity/AccountActivationTest.php | 2 + .../Identity/PasswordForgottenTest.php | 70 +++++++++++++++++++ .../App/Account/Identity/RegisterTest.php | 4 +- 6 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 tests/Integration/App/Account/Identity/PasswordForgottenTest.php diff --git a/src/App/Account/Identity/src/ConfigProvider.php b/src/App/Account/Identity/src/ConfigProvider.php index 5c2f1034..50d20c28 100644 --- a/src/App/Account/Identity/src/ConfigProvider.php +++ b/src/App/Account/Identity/src/ConfigProvider.php @@ -15,6 +15,7 @@ use Exdrals\Identity\Infrastructure\Service\Account\AccountService; use Exdrals\Identity\Infrastructure\Service\Account\PasswordChangeService; use Exdrals\Identity\Infrastructure\Service\Account\PasswordService; +use Exdrals\Identity\Infrastructure\Service\Account\PasswordServiceInterface; use Exdrals\Identity\Infrastructure\Service\Authentication\AuthenticationService; use Exdrals\Identity\Infrastructure\Service\ClientIdentification\ClientIdentificationService; use Exdrals\Identity\Infrastructure\Service\Token\AccessTokenService; @@ -27,7 +28,6 @@ use Exdrals\Identity\Infrastructure\Validator\Input\AccountNameInput; use Exdrals\Identity\Infrastructure\Validator\Input\PasswordInput; use Exdrals\Identity\Infrastructure\Validator\PasswordValidator; -use Exdrals\Identity\Middleware\IdentityExceptionMappingMiddleware; use Exdrals\Mailing\Infrastructure\EmailService; use Exdrals\Mailing\Infrastructure\EmailServiceFactory; use Exdrals\Mailing\Infrastructure\Validator\EMailValidator; diff --git a/src/App/Account/Identity/src/Handler/AccountPasswordForgottenHandler.php b/src/App/Account/Identity/src/Handler/AccountPasswordForgottenHandler.php index 14f4cec5..7355e58f 100644 --- a/src/App/Account/Identity/src/Handler/AccountPasswordForgottenHandler.php +++ b/src/App/Account/Identity/src/Handler/AccountPasswordForgottenHandler.php @@ -12,7 +12,7 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -class AccountPasswordForgottenHandler implements RequestHandlerInterface +readonly class AccountPasswordForgottenHandler implements RequestHandlerInterface { public function __construct( private PasswordService $passwordService, diff --git a/src/App/Account/Identity/src/Infrastructure/Service/Account/PasswordService.php b/src/App/Account/Identity/src/Infrastructure/Service/Account/PasswordService.php index 53b2c9de..6fce71fa 100644 --- a/src/App/Account/Identity/src/Infrastructure/Service/Account/PasswordService.php +++ b/src/App/Account/Identity/src/Infrastructure/Service/Account/PasswordService.php @@ -29,7 +29,5 @@ public function sendTokenForInitiateResetPassword(EmailType $email): void } $this->accountService->sendTokenForPasswordChange($email); - - return; } } diff --git a/tests/Integration/App/Account/Identity/AccountActivationTest.php b/tests/Integration/App/Account/Identity/AccountActivationTest.php index a7fc9d05..7d882913 100644 --- a/tests/Integration/App/Account/Identity/AccountActivationTest.php +++ b/tests/Integration/App/Account/Identity/AccountActivationTest.php @@ -1,5 +1,7 @@ createJsonPostRequest( + '/api/account/password/forgotten', + ['email' => $account['email']] + ); + + $service = $this->container->get(PasswordService::class); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(200) + ->and(fn() => $service->sendTokenForInitiateResetPassword( + EmailType::fromString($account['email']) + )) + ->not->toThrow(HttpHandledInvalidArgumentAsSuccessException::class); +}); + +it('returns 200, despite an invalid email address being provided', function () { + $email = Faker::create()->safeEmail(); + + $request = $this->createJsonPostRequest( + '/api/account/password/forgotten', + ['email' => $email] + ); + + $service = $this->container->get(PasswordService::class); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(200) + ->and(fn() => $service->sendTokenForInitiateResetPassword( + EmailType::fromString($email) + )) + ->toThrow(HttpHandledInvalidArgumentAsSuccessException::class); +}); + +it('returns 400 when email is invalid', function ($email) { + $request = $this->createJsonPostRequest( + '/api/account/password/forgotten', + [ + 'email' => $email, + ] + ); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +})->with([ + 'invalidate.com', + 'user@', + '@domain.com', + 'user..name@domain.com', + 'user:name@domain.com', + 'user@domain!.com', + 'user@domain', + 'user name@domain.com', + 'user@domain .com', + 'user@domain..com', + 'user@-domain.com', + 'test@example.invalid', + 'test@example.web', +]); diff --git a/tests/Integration/App/Account/Identity/RegisterTest.php b/tests/Integration/App/Account/Identity/RegisterTest.php index c53a70f5..042ef124 100644 --- a/tests/Integration/App/Account/Identity/RegisterTest.php +++ b/tests/Integration/App/Account/Identity/RegisterTest.php @@ -1,12 +1,12 @@ Date: Tue, 3 Feb 2026 01:32:15 +0100 Subject: [PATCH 14/17] test: add integration tests and factories for password change flow --- .../Hydrator/Token/TokenHydrator.php | 2 +- .../Factory/PasswordChangeFactory.php | 33 +++++++ .../Account/Identity/PasswordChangeTest.php | 99 +++++++++++++++++++ tests/TestIntegrationCase.php | 18 ++-- 4 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 tests/Integration/App/Account/Identity/Factory/PasswordChangeFactory.php create mode 100644 tests/Integration/App/Account/Identity/PasswordChangeTest.php diff --git a/src/App/Account/Identity/src/Infrastructure/Hydrator/Token/TokenHydrator.php b/src/App/Account/Identity/src/Infrastructure/Hydrator/Token/TokenHydrator.php index c33ad1c1..233b3057 100644 --- a/src/App/Account/Identity/src/Infrastructure/Hydrator/Token/TokenHydrator.php +++ b/src/App/Account/Identity/src/Infrastructure/Hydrator/Token/TokenHydrator.php @@ -24,7 +24,7 @@ public function hydrate(array $data): TokenInterface return new Token( id: $data['id'], accountId: $data['accountId'], - tokenType: TokenType::EMail, + tokenType: TokenType::from((int) $data['tokenType']), token: $this->uuid->fromString($data['token']), createdAt: new DateTimeImmutable($data['createdAt']), ); diff --git a/tests/Integration/App/Account/Identity/Factory/PasswordChangeFactory.php b/tests/Integration/App/Account/Identity/Factory/PasswordChangeFactory.php new file mode 100644 index 00000000..95ab4d84 --- /dev/null +++ b/tests/Integration/App/Account/Identity/Factory/PasswordChangeFactory.php @@ -0,0 +1,33 @@ +getContainer(); + $fluent = $container->get(Query::class); + + $account = AccountFactory::create(); + + $defaults = [ + 'accountId' => $account['id'], + 'token' => $faker->unique()->uuid(), + 'tokenType' => TokenType::EMail->value, + ]; + + $data = array_merge($defaults, $attributes); + + $id = $fluent->insertInto('Token', $data)->execute(); + $data['id'] = $id; + + return $data; + } +} diff --git a/tests/Integration/App/Account/Identity/PasswordChangeTest.php b/tests/Integration/App/Account/Identity/PasswordChangeTest.php new file mode 100644 index 00000000..aedb4456 --- /dev/null +++ b/tests/Integration/App/Account/Identity/PasswordChangeTest.php @@ -0,0 +1,99 @@ +createJsonPatchRequest( + '/api/account/password/' . $passwordChange['token'], + [ + 'password' => Faker::create('de_DE')->password(8), + ] + ); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_OK) + ->and('Token')->toNotHaveRecord(['token' => $passwordChange['token']]); +}); + +test('Can not use the same token twice', function () { + $passwordChange = PasswordChangeFactory::create(); + + $request = $this->createJsonPatchRequest( + '/api/account/password/' . $passwordChange['token'], + [ + 'password' => Faker::create('de_DE')->password(8), + ] + ); + + $this->app->handle($request); + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST) + ->and('Token')->toNotHaveRecord(['token' => $passwordChange['token']]); +}); + + + +test('Token present in the database but account does not exist', function () { + $passwordChange = PasswordChangeFactory::create(); + $fluent = $this->getContainer()->get(Query::class); + $fluent->deleteFrom('Token')->where('accountId', $passwordChange['accountId'])->execute(); + + $request = $this->createJsonPatchRequest( + '/api/account/password/' . $passwordChange['token'], + [ + 'password' => Faker::create('de_DE')->password(8), + ] + ); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +test('Token is invalid', function () { + PasswordChangeFactory::create(); + + $request = $this->createJsonPatchRequest( + '/api/account/password/' . Faker::create('de_DE')->uuid(), + [ + 'password' => Faker::create('de_DE')->password(8), + ] + ); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +test('Token has incorrect type', function () { + $passwordChange = PasswordChangeFactory::create([ + 'tokenType' => \Exdrals\Shared\Domain\Enum\Token\TokenType::Default->value, + ]); + + $request = $this->createJsonPatchRequest( + '/api/account/password/' . $passwordChange['token'], + [ + 'password' => Faker::create('de_DE')->password(8), + ] + ); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +test('New password invalid', function () { + $passwordChange = PasswordChangeFactory::create(); + + $request = $this->createJsonPatchRequest( + '/api/account/password/' . $passwordChange['token'], + [ + 'password' => Faker::create('de_DE')->password(1, 5), + ] + ); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); diff --git a/tests/TestIntegrationCase.php b/tests/TestIntegrationCase.php index 96dca63c..219a3599 100644 --- a/tests/TestIntegrationCase.php +++ b/tests/TestIntegrationCase.php @@ -52,18 +52,12 @@ public function getContainer(): ContainerInterface return $this->container; } - /** - * Hilfsmethode, um einen GET Request zu erstellen - */ public function createGetRequest(string $path): ServerRequest { return (new ServerRequestFactory()) ->createServerRequest('GET', new Uri($path)); } - /** - * Hilfsmethode, um einen POST Request mit JSON Body zu erstellen - */ public function createJsonPostRequest(string $path, array $data): ServerRequest { $request = (new ServerRequestFactory()) @@ -76,6 +70,18 @@ public function createJsonPostRequest(string $path, array $data): ServerRequest return $request; } + public function createJsonPatchRequest(string $path, array $data): ServerRequest + { + $request = (new ServerRequestFactory()) + ->createServerRequest('PATCH', new Uri($path)) + ->withHeader('Content-Type', 'application/json'); + + $request->getBody()->write(json_encode($data)); + $request->getBody()->rewind(); + + return $request; + } + public function insert(string $table, array $data): void { /** @var PDO $pdo */ From 608727ca42145714c002c14c061ee3bf33c199ca Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Wed, 4 Feb 2026 00:05:41 +0100 Subject: [PATCH 15/17] test: add integration tests and middleware for logout flow --- public/api/docs/swagger.json | 40 +++++- .../Account/Identity/src/ConfigProvider.php | 9 +- .../src/Domain/Message/IdentityLogMessage.php | 1 + .../Identity/src/Handler/LogoutHandler.php | 58 +++++---- .../Service/Account/AccountService.php | 26 ++-- ...efreshTokenViaBodyValidationMiddleware.php | 41 ++++++ .../App/Account/Identity/LogoutTest.php | 120 ++++++++++++++++++ 7 files changed, 248 insertions(+), 47 deletions(-) create mode 100644 src/App/Account/Identity/src/Middleware/Token/RefreshTokenViaBodyValidationMiddleware.php create mode 100644 tests/Integration/App/Account/Identity/LogoutTest.php diff --git a/public/api/docs/swagger.json b/public/api/docs/swagger.json index 702d960d..8c853630 100644 --- a/public/api/docs/swagger.json +++ b/public/api/docs/swagger.json @@ -247,26 +247,54 @@ } }, "/account/logout": { - "get": { + "post": { "tags": [ "Account" ], - "summary": "Log out the current user", - "description": "Terminates the user session by invalidating the current access token. Clients should delete all locally stored tokens (Access Token and Refresh Token) after a successful logout.", + "summary": "Log out the current user and invalidate the session", + "description": "Terminates the user session by invalidating the provided refresh token in the database. The access token must be provided in the header for authentication, while the refresh token is required in the request body to identify the specific session to be closed.", "operationId": "logout", + "requestBody": { + "description": "The refresh token that should be invalidated.", + "required": true, + "content": { + "application/json": { + "schema": { + "properties": { + "refreshToken": { + "description": "The full refresh token string", + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + } + }, + "type": "object" + } + } + } + }, "responses": { "200": { - "description": "Logout successful. The session has been invalidated.", + "description": "Logout successful. The refresh token has been deleted and the session is invalidated.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AuthenticationResponse" + "$ref": "#/components/schemas/HttpResponseMessage" + } + } + } + }, + "400": { + "description": "Bad Request. The refresh token is missing in the body or is malformed.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HttpResponseMessage" } } } }, "401": { - "description": "Unauthorized. The access token is missing, expired, or already invalid.", + "description": "Unauthorized. The access token is missing, expired, or the user could not be identified.", "content": { "application/json": { "schema": { diff --git a/src/App/Account/Identity/src/ConfigProvider.php b/src/App/Account/Identity/src/ConfigProvider.php index 50d20c28..0e8d67d9 100644 --- a/src/App/Account/Identity/src/ConfigProvider.php +++ b/src/App/Account/Identity/src/ConfigProvider.php @@ -15,14 +15,12 @@ use Exdrals\Identity\Infrastructure\Service\Account\AccountService; use Exdrals\Identity\Infrastructure\Service\Account\PasswordChangeService; use Exdrals\Identity\Infrastructure\Service\Account\PasswordService; -use Exdrals\Identity\Infrastructure\Service\Account\PasswordServiceInterface; use Exdrals\Identity\Infrastructure\Service\Authentication\AuthenticationService; use Exdrals\Identity\Infrastructure\Service\ClientIdentification\ClientIdentificationService; use Exdrals\Identity\Infrastructure\Service\Token\AccessTokenService; use Exdrals\Identity\Infrastructure\Service\Token\ActivationTokenService; use Exdrals\Identity\Infrastructure\Service\Token\PasswordTokenService; use Exdrals\Identity\Infrastructure\Service\Token\RefreshTokenService; -use Exdrals\Identity\Infrastructure\Service\Token\RefreshTokenServiceInterface; use Exdrals\Identity\Infrastructure\Validator\AccountActivationValidator; use Exdrals\Identity\Infrastructure\Validator\AuthenticationValidator; use Exdrals\Identity\Infrastructure\Validator\Input\AccountNameInput; @@ -133,11 +131,12 @@ public function getRoutes(): array [ 'path' => '/api/account/logout[/]', - 'allowed_methods' => ['GET'], + 'allowed_methods' => ['POST'], 'middleware' => [ Middleware\IdentityExceptionMappingMiddleware::class, RequireLoginMiddleware::class, Middleware\Token\AccessTokenValidationMiddleware::class, + Middleware\Token\RefreshTokenViaBodyValidationMiddleware::class, Handler\LogoutHandler::class, ], 'name' => 'api_identity_logout', @@ -193,6 +192,7 @@ public function getDependencies(): array Middleware\Token\RefreshTokenDatabaseExistenceMiddleware::class => ConfigAbstractFactory::class, Middleware\Token\RefreshTokenMatchClientIdentificationMiddleware::class => InvokableFactory::class, Middleware\Token\RefreshTokenValidationMiddleware::class => ConfigAbstractFactory::class, + Middleware\Token\RefreshTokenViaBodyValidationMiddleware::class => ConfigAbstractFactory::class, Infrastructure\Persistence\Repository\Account\AccountAccessAuthRepository::class => ConfigAbstractFactory::class, Infrastructure\Persistence\Repository\Account\AccountActivationRepository::class => ConfigAbstractFactory::class, Infrastructure\Persistence\Repository\Account\AccountRepository::class => ConfigAbstractFactory::class, @@ -286,6 +286,9 @@ public function getAbstractFactoryConfig(): array Middleware\Token\RefreshTokenValidationMiddleware::class => [ RefreshTokenService::class, ], + Middleware\Token\RefreshTokenViaBodyValidationMiddleware::class => [ + RefreshTokenService::class, + ], Infrastructure\Persistence\Repository\Account\AccountAccessAuthRepository::class => [ AccountAccessAuthStoreInterface::class, ], diff --git a/src/App/Account/Identity/src/Domain/Message/IdentityLogMessage.php b/src/App/Account/Identity/src/Domain/Message/IdentityLogMessage.php index 701af59a..641b9f75 100644 --- a/src/App/Account/Identity/src/Domain/Message/IdentityLogMessage.php +++ b/src/App/Account/Identity/src/Domain/Message/IdentityLogMessage.php @@ -28,6 +28,7 @@ interface IdentityLogMessage extends LogMessage // --- 4. Logout Context --- public const string LOGOUT_REQUIRES_AUTHENTICATION = 'Logout failed: User is not authenticated'; public const string LOGOUT_CLIENT_IDENTITY_MISMATCH = 'Logout failed: Client identification mismatch for the account'; + public const string LOGOUT_REFRESH_TOKEN_MISMATCH = 'Logout failed: Refresh Token mismatch for the account'; // --- 5. Activation Tokens --- public const string ACTIVATION_TOKEN_MISSING = 'No activation token was provided'; diff --git a/src/App/Account/Identity/src/Handler/LogoutHandler.php b/src/App/Account/Identity/src/Handler/LogoutHandler.php index aed2c4b2..473718a9 100644 --- a/src/App/Account/Identity/src/Handler/LogoutHandler.php +++ b/src/App/Account/Identity/src/Handler/LogoutHandler.php @@ -2,17 +2,13 @@ namespace Exdrals\Identity\Handler; -use Exdrals\Identity\Domain\Message\IdentityLogMessage; use Exdrals\Identity\Domain\Message\IdentityStatusMessage; -use Exdrals\Identity\DTO\Client\ClientIdentification; -use Exdrals\Identity\DTO\Response\AuthenticationResponse; use Exdrals\Identity\DTO\Response\HttpResponseMessage; +use Exdrals\Identity\DTO\Token\RefreshToken; use Exdrals\Identity\Infrastructure\Service\Account\AccountService; use Exdrals\Shared\Domain\Account\AccountInterface; -use Exdrals\Shared\Domain\Exception\HttpUnauthorizedException; use Fig\Http\Message\StatusCodeInterface as HTTP; use Laminas\Diactoros\Response\JsonResponse; -use Monolog\Level; use OpenApi\Attributes as OA; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -25,42 +21,54 @@ public function __construct( ) { } - #[OA\Get( + #[OA\Post( path: '/account/logout', operationId: 'logout', - description: 'Terminates the user session by invalidating the current access token. ' . - 'Clients should delete all locally stored tokens (Access Token and Refresh Token) after a successful logout.', - summary: 'Log out the current user', + description: 'Terminates the user session by invalidating the provided refresh token in the database. ' . + 'The access token must be provided in the header for authentication, while the refresh token is required ' . + 'in the request body to identify the specific session to be closed.', + summary: 'Log out the current user and invalidate the session', security: [['accessToken' => []]], tags: ['Account'] )] + #[OA\RequestBody( + description: 'The refresh token that should be invalidated.', + required: true, + content: new OA\JsonContent( + properties: [ + new OA\Property( + property: 'refreshToken', + description: 'The full refresh token string', + type: 'string', + example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' + ), + ], + type: 'object' + ) + )] + #[OA\Response( + response: HTTP::STATUS_NO_CONTENT, + description: 'Logout successful. The refresh token has been deleted and the session is invalidated.', + content: [new OA\JsonContent(ref: HttpResponseMessage::class)] + )] #[OA\Response( - response: HTTP::STATUS_OK, - description: 'Logout successful. The session has been invalidated.', - content: [new OA\JsonContent(ref: AuthenticationResponse::class)] + response: HTTP::STATUS_BAD_REQUEST, + description: 'Bad Request. The refresh token is missing in the body or is malformed.', + content: [new OA\JsonContent(ref: HttpResponseMessage::class)] )] #[OA\Response( response: HTTP::STATUS_UNAUTHORIZED, - description: 'Unauthorized. The access token is missing, expired, or already invalid.', + description: 'Unauthorized. The access token is missing, expired, or the user could not be identified.', content: [new OA\JsonContent(ref: HttpResponseMessage::class)] )] public function handle(ServerRequestInterface $request): ResponseInterface { $account = $request->getAttribute(AccountInterface::AUTHENTICATED); - $clientId = $request->getAttribute(ClientIdentification::class); - - if (!($account instanceof AccountInterface)) { - throw new HttpUnauthorizedException( - IdentityLogMessage::LOGOUT_REQUIRES_AUTHENTICATION, - IdentityStatusMessage::UNAUTHORIZED_ACCESS, - [], - Level::Warning - ); - } + $refreshToken = $request->getAttribute(RefreshToken::class); - $this->accountService->logout($account, $clientId); + $this->accountService->logout($account, $refreshToken); - $response = HttpResponseMessage::create(HTTP::STATUS_OK, IdentityStatusMessage::SUCCESS); + $response = HttpResponseMessage::create(HTTP::STATUS_NO_CONTENT, IdentityStatusMessage::SUCCESS); return new JsonResponse($response, $response->statusCode); } diff --git a/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountService.php b/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountService.php index bb318e63..61cbc4e5 100644 --- a/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountService.php +++ b/src/App/Account/Identity/src/Infrastructure/Service/Account/AccountService.php @@ -6,7 +6,7 @@ use Exdrals\Identity\Domain\Message\IdentityLogMessage; use Exdrals\Identity\Domain\Message\IdentityStatusMessage; use Exdrals\Identity\Domain\Token; -use Exdrals\Identity\DTO\Client\ClientIdentification; +use Exdrals\Identity\DTO\Token\RefreshToken; use Exdrals\Identity\Infrastructure\Service\Token\PasswordTokenService; use Exdrals\Mailing\Domain\EmailType; use Exdrals\Shared\Domain\Account\AccountAccessAuthInterface; @@ -69,29 +69,29 @@ public function updateLastAction(AccountInterface $account): void ); } - public function logout(?AccountInterface $account, ClientIdentification $clientId): void + public function logout(AccountInterface $account, RefreshToken $refreshToken): void { - if (!($account instanceof AccountInterface)) { + $accountAccessAuth = $this->authRepository->findByRefreshToken($refreshToken->refreshToken); + + if (!($accountAccessAuth instanceof AccountAccessAuthInterface)) { throw new HttpUnauthorizedException( - IdentityLogMessage::LOGOUT_REQUIRES_AUTHENTICATION, + IdentityLogMessage::LOGOUT_REFRESH_TOKEN_MISMATCH, IdentityStatusMessage::UNAUTHORIZED_ACCESS, - [], + [ + 'accountId' => $account->id, + 'refreshToken' => $refreshToken->refreshToken, + ], Level::Warning ); } - $accountAccessAuth = $this->authRepository->findByAccountIdAndClientIdHash( - $account->id, - $clientId->identificationHash - ); - - if (!($accountAccessAuth instanceof AccountAccessAuthInterface)) { + if ($account->id !== $accountAccessAuth->accountId) { throw new HttpUnauthorizedException( - IdentityLogMessage::LOGOUT_CLIENT_IDENTITY_MISMATCH, + IdentityLogMessage::LOGOUT_REFRESH_TOKEN_MISMATCH, IdentityStatusMessage::UNAUTHORIZED_ACCESS, [ 'accountId' => $account->id, - 'clientIdentificationHash' => $clientId->identificationHash, + 'refreshToken' => $refreshToken->refreshToken, ], Level::Warning ); diff --git a/src/App/Account/Identity/src/Middleware/Token/RefreshTokenViaBodyValidationMiddleware.php b/src/App/Account/Identity/src/Middleware/Token/RefreshTokenViaBodyValidationMiddleware.php new file mode 100644 index 00000000..30e97763 --- /dev/null +++ b/src/App/Account/Identity/src/Middleware/Token/RefreshTokenViaBodyValidationMiddleware.php @@ -0,0 +1,41 @@ +getParsedBody(); + $refreshToken = $refreshToken['refreshToken'] ?? null; + + if (!$refreshToken || !$this->tokenService->isValid($refreshToken)) { + throw new HttpUnauthorizedException( + IdentityLogMessage::REFRESH_TOKEN_INVALID, + IdentityStatusMessage::TOKEN_INVALID, + [ + 'Refresh Token:' => $refreshToken, + ], + ); + } + + $refreshToken = RefreshToken::fromString($refreshToken); + + return $handler->handle($request->withAttribute(RefreshToken::class, $refreshToken)); + } +} diff --git a/tests/Integration/App/Account/Identity/LogoutTest.php b/tests/Integration/App/Account/Identity/LogoutTest.php new file mode 100644 index 00000000..eb1c2b05 --- /dev/null +++ b/tests/Integration/App/Account/Identity/LogoutTest.php @@ -0,0 +1,120 @@ +createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + $response = $this->app->handle($request); + $jsonResponse = JsonFactory::create($response); + + $request = $this->createJsonPostRequest( + '/api/account/logout', + [ + 'refreshToken' => $jsonResponse['refreshToken'], + ] + ) + ->withHeader('Authorization', $jsonResponse['accessToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_NO_CONTENT) + ->and('AccountAccessAuth')->toNotHaveRecord(['refreshToken' => $jsonResponse['refreshToken']]); +}); + +test('Access Token invalid', function () { + $account = AccountFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + $response = $this->app->handle($request); + $jsonResponse = JsonFactory::create($response); + + $request = $this->createJsonPostRequest( + '/api/account/logout', + [ + 'refreshToken' => $jsonResponse['refreshToken'], + ] + ) + ->withHeader('Authorization', $jsonResponse['refreshToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Refresh Token invalid', function () { + $account = AccountFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + $response = $this->app->handle($request); + $jsonResponse = JsonFactory::create($response); + $request = $this->createJsonPostRequest( + '/api/account/logout', + [ + 'refreshToken' => $jsonResponse['accessToken'], + ] + ) + ->withHeader('Authorization', $jsonResponse['accessToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +it('has not authorization', function () { + $account = AccountFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + $response = $this->app->handle($request); + $jsonResponse = JsonFactory::create($response); + $request = $this->createJsonPostRequest( + '/api/account/logout', + [ + 'refreshToken' => $jsonResponse['accessToken'], + ] + ); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +it('has no body content', function () { + $account = AccountFactory::create(); + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + $response = $this->app->handle($request); + $jsonResponse = JsonFactory::create($response); + $request = $this->createJsonPostRequest( + '/api/account/logout', + [] + ) + ->withHeader('Authorization', $jsonResponse['accessToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); From 46cda4aba31a9366778d41b03d83107b1ad5a513 Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Wed, 4 Feb 2026 01:53:15 +0100 Subject: [PATCH 16/17] test: add integration tests for workspace creation flow --- composer.json | 2 - .../App/Workspace/WorkspaceCreateTest.php | 101 ++++++++++++++++++ tests/TestIntegrationCase.php | 40 +++---- 3 files changed, 121 insertions(+), 22 deletions(-) create mode 100644 tests/Integration/App/Workspace/WorkspaceCreateTest.php diff --git a/composer.json b/composer.json index ccf6107f..67db4f7b 100644 --- a/composer.json +++ b/composer.json @@ -93,8 +93,6 @@ }, "autoload-dev": { "psr-4": { - "FunctionalTest\\": "tests/FunctionalTest/", - "UnitTest\\": "tests/UnitTest/", "Tests\\": "tests/" } }, diff --git a/tests/Integration/App/Workspace/WorkspaceCreateTest.php b/tests/Integration/App/Workspace/WorkspaceCreateTest.php new file mode 100644 index 00000000..393ab00b --- /dev/null +++ b/tests/Integration/App/Workspace/WorkspaceCreateTest.php @@ -0,0 +1,101 @@ +createAndLoginUser(); + $name = Faker::create()->regexify('[A-Za-z0-9][A-Za-z0-9 _-]{10,30}'); + $description = Faker::create()->text(50); + $request = $this->createJsonPostRequest( + '/api/workspace', + [ + 'name' => $name, + 'description' => $description, + ] + ) + ->withHeader('Authorization', $account['accessToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_CREATED) + ->and('Workspace')->toHaveRecord( + [ + 'accountId' => $account['id'], + 'name' => $name, + 'description' => $description, + ] + ); +}); + +test('Authorization missed', function () { + $request = $this->createJsonPostRequest( + '/api/workspace', + [ + 'name' => Faker::create()->regexify('[A-Za-z0-9][A-Za-z0-9 _-]{10,30}'), + 'description' => Faker::create()->text(50), + ] + ); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Authorization failed', function () { + $account = $this->createAndLoginUser(); + $request = $this->createJsonPostRequest( + '/api/workspace', + [ + 'name' => Faker::create()->regexify('[A-Za-z0-9][A-Za-z0-9 _-]{10,30}'), + 'description' => Faker::create()->text(50), + ] + )->withHeader('Authorization', $account['refreshToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_UNAUTHORIZED); +}); + +test('Workspace name to short', function () { + $account = $this->createAndLoginUser(); + $request = $this->createJsonPostRequest( + '/api/workspace', + [ + 'name' => '12', + 'description' => Faker::create()->text(50), + ] + )->withHeader('Authorization', $account['accessToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +test('Workspace name to long', function () { + $account = $this->createAndLoginUser(); + $request = $this->createJsonPostRequest( + '/api/workspace', + [ + 'name' => Faker::create()->regexify('[A-Za-z0-9][A-Za-z0-9 _-]{100,200}'), + 'description' => Faker::create()->text(50), + ] + )->withHeader('Authorization', $account['accessToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); + +test('Workspace name has invalid characters', function () { + $account = $this->createAndLoginUser(); + $request = $this->createJsonPostRequest( + '/api/workspace', + [ + 'name' => Faker::create()->regexify('[!@#$%^&*][A-Za-z0-9 _-]{10,30}'), + 'description' => Faker::create()->text(50), + ] + )->withHeader('Authorization', $account['accessToken']); + + $response = $this->app->handle($request); + expect($response->getStatusCode())->toBe(Http::STATUS_BAD_REQUEST); +}); diff --git a/tests/TestIntegrationCase.php b/tests/TestIntegrationCase.php index 219a3599..b384e913 100644 --- a/tests/TestIntegrationCase.php +++ b/tests/TestIntegrationCase.php @@ -11,8 +11,10 @@ use PHPUnit\Framework\TestCase as BaseTestCase; use Psr\Container\ContainerInterface; use RuntimeException; +use Tests\Integration\App\Account\Identity\Factory\AccountFactory; +use Tests\Integration\JsonFactory; -// <--- Wichtig +use function array_merge; abstract class TestIntegrationCase extends BaseTestCase { @@ -36,16 +38,11 @@ protected function setUp(): void public function getContainer(): ContainerInterface { - // Singleton-Logik: Container nur einmal pro Testlauf laden, um Performance zu sparen if ($this->container === null) { - // Pfad anpassen: Gehen Sie vom 'tests'-Ordner zurück ins Root-Verzeichnis - // Meistens liegt die container.php in config/container.php $path = __DIR__ . '/../config/container.php'; - if (!file_exists($path)) { throw new RuntimeException("Container-Konfiguration nicht gefunden unter: $path"); } - $this->container = require $path; } @@ -95,19 +92,22 @@ public function insert(string $table, array $data): void $sql = "INSERT INTO $table ($cols) VALUES ($placeholders)"; $pdo->prepare($sql)->execute(array_values($data)); } - /* - test('user can log in', function () + + public function createAndLoginUser(): array { - // Vorbereitung (Arrange) - insert('users', [ - 'email' => 'user@example.com', - 'password' => password_hash('secret', PASSWORD_DEFAULT), - ]); - - // Ausführung (Act) - $response = $this->app->handle(...); - - expect($response->getStatusCode())->toBe(200); - }); - */ + $account = AccountFactory::create(); + + $request = $this->createJsonPostRequest( + '/api/account/authentication', + [ + 'email' => $account['email'], + 'password' => $account['password'], + ] + ); + $response = $this->app->handle($request); + + $responseDate = JsonFactory::create($response); + + return array_merge($account, $responseDate); + } } From 416c850e90b7b961ff528bd1c5718102da3d429f Mon Sep 17 00:00:00 2001 From: BibaltiK Date: Wed, 4 Feb 2026 22:53:40 +0100 Subject: [PATCH 17/17] test: remove backup test files and obsolete test classes --- composer.json | 4 +- composer.lock | 76 +++-- .../FunctionalTest/AbstractFunctional.php | 92 ------ .../Root/Account/AccessTokenHandlerTest.php | 272 ------------------ .../AccountPasswordForgottenHandlerTest.php | 61 ---- .../Account/AccountPasswordHandlerTest.php | 134 --------- .../FunctionalTest/Root/PingHandlerTest.php | 29 -- .../ListOwnWorkspacesHandlerTest.php | 97 ------- .../Workspace/WorkspaceCreateHandlerTest.php | 175 ----------- tests_backup/FunctionalTest/bootstrap.php | 10 - ...on20990921210156_InsertAccountTestData.php | 32 --- ...20990921210157_InsertWorkspaceTestData.php | 32 --- .../AppTest/Handler/AbstractTestHandler.php | 24 -- .../AppTest/Handler/PingHandlerTest.php | 29 -- .../AccountAccessAuthHydratorTest.php | 55 ---- .../AppTest/Hydrator/AccountHydratorTest.php | 66 ----- .../Middleware/AbstractTestMiddleware.php | 28 -- ...AccountAccessAuthPersistMiddlewareTest.php | 108 ------- .../AccountAuthenticationMiddlewareTest.php | 107 ------- ...AuthenticationConditionsMiddlewareTest.php | 42 --- ...AuthenticationValidationMiddlewareTest.php | 33 --- .../ClientIdentificationMiddlewareTest.php | 36 --- .../GenerateAccessTokenMiddlewareTest.php | 34 --- .../GenerateRefreshTokenMiddlewareTest.php | 39 --- .../AccountAccessAuthRepositoryTest.php | 194 ------------- .../Repository/AccountRepositoryTest.php | 161 ----------- .../Service/AccessTokenServiceTest.php | 48 ---- .../Service/AuthenticationServiceTest.php | 31 -- .../Service/RefreshTokenServiceTest.php | 51 ---- .../Table/AccountAccessAuthTableTest.php | 226 --------------- .../AppTest/Table/AccountTableTest.php | 189 ------------ .../CoreTest/Factory/DatabaseFactoryTest.php | 43 --- .../CoreTest/Factory/QueryFactoryTest.php | 29 -- tests_backup/UnitTest/JsonRequestHelper.php | 15 - .../UnitTest/Mock/Constants/Account.php | 60 ---- .../Mock/Constants/AccountAccessAuth.php | 54 ---- .../UnitTest/Mock/Constants/Token.php | 21 -- .../UnitTest/Mock/Database/MockDelete.php | 27 -- .../Mock/Database/MockDeleteFailed.php | 24 -- .../UnitTest/Mock/Database/MockInsert.php | 27 -- .../Mock/Database/MockInsertFailed.php | 25 -- .../UnitTest/Mock/Database/MockPDO.php | 18 -- .../UnitTest/Mock/Database/MockQuery.php | 37 --- .../Mock/Database/MockQueryFailed.php | 37 --- .../UnitTest/Mock/Database/MockSelect.php | 96 ------- .../Mock/Database/MockSelectFailed.php | 36 --- .../UnitTest/Mock/Database/MockUpdate.php | 22 -- .../Mock/Database/MockUpdateFailed.php | 19 -- .../UnitTest/Mock/Entity/MockAccount.php | 56 ---- ...AuthenticationMiddlewareRequestHandler.php | 24 -- tests_backup/UnitTest/Mock/MockContainer.php | 32 --- .../UnitTest/Mock/MockRequestHandler.php | 15 - tests_backup/UnitTest/Mock/MockResponse.php | 84 ------ .../UnitTest/Mock/MockServerRequest.php | 192 ------------- .../MockAccountAccessAuthRepository.php | 14 - .../Mock/Repository/MockAccountRepository.php | 14 - ...ntAuthenticationMiddlewareInvalidToken.php | 14 - .../Mock/Service/MockAccessTokenService.php | 36 --- .../MockAccessTokenServiceWithoutDuration.php | 36 --- .../Service/MockAuthenticationService.php | 14 - .../MockClientIdentificationService.php | 9 - .../Mock/Service/MockRefreshTokenService.php | 23 -- .../Mock/Table/MockAccountAccessAuthTable.php | 108 ------- .../MockAccountAccessAuthTableFailed.php | 25 -- .../UnitTest/Mock/Table/MockAccountTable.php | 84 ------ ...ntAuthenticationMiddlewareInvalidToken.php | 84 ------ .../Mock/Table/MockAccountTableFailed.php | 26 -- .../Validator/MockAuthenticationValidator.php | 20 -- .../MockAuthenticationValidatorFailed.php | 20 -- 69 files changed, 47 insertions(+), 3988 deletions(-) delete mode 100644 tests_backup/FunctionalTest/AbstractFunctional.php delete mode 100644 tests_backup/FunctionalTest/Root/Account/AccessTokenHandlerTest.php delete mode 100644 tests_backup/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php delete mode 100644 tests_backup/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php delete mode 100644 tests_backup/FunctionalTest/Root/PingHandlerTest.php delete mode 100644 tests_backup/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php delete mode 100644 tests_backup/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php delete mode 100644 tests_backup/FunctionalTest/bootstrap.php delete mode 100644 tests_backup/FunctionalTest/database/migrations/Version20990921210156_InsertAccountTestData.php delete mode 100644 tests_backup/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php delete mode 100644 tests_backup/UnitTest/AppTest/Handler/AbstractTestHandler.php delete mode 100644 tests_backup/UnitTest/AppTest/Handler/PingHandlerTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Hydrator/AccountHydratorTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php delete mode 100644 tests_backup/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Repository/AccountRepositoryTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Service/AccessTokenServiceTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Service/AuthenticationServiceTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Service/RefreshTokenServiceTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php delete mode 100644 tests_backup/UnitTest/AppTest/Table/AccountTableTest.php delete mode 100644 tests_backup/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php delete mode 100644 tests_backup/UnitTest/CoreTest/Factory/QueryFactoryTest.php delete mode 100644 tests_backup/UnitTest/JsonRequestHelper.php delete mode 100644 tests_backup/UnitTest/Mock/Constants/Account.php delete mode 100644 tests_backup/UnitTest/Mock/Constants/AccountAccessAuth.php delete mode 100644 tests_backup/UnitTest/Mock/Constants/Token.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockDelete.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockDeleteFailed.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockInsert.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockInsertFailed.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockPDO.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockQuery.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockQueryFailed.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockSelect.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockSelectFailed.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockUpdate.php delete mode 100644 tests_backup/UnitTest/Mock/Database/MockUpdateFailed.php delete mode 100644 tests_backup/UnitTest/Mock/Entity/MockAccount.php delete mode 100644 tests_backup/UnitTest/Mock/MockAccountAuthenticationMiddlewareRequestHandler.php delete mode 100644 tests_backup/UnitTest/Mock/MockContainer.php delete mode 100644 tests_backup/UnitTest/Mock/MockRequestHandler.php delete mode 100644 tests_backup/UnitTest/Mock/MockResponse.php delete mode 100644 tests_backup/UnitTest/Mock/MockServerRequest.php delete mode 100644 tests_backup/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php delete mode 100644 tests_backup/UnitTest/Mock/Repository/MockAccountRepository.php delete mode 100644 tests_backup/UnitTest/Mock/Repository/MockAccountRepositoryAccountAuthenticationMiddlewareInvalidToken.php delete mode 100644 tests_backup/UnitTest/Mock/Service/MockAccessTokenService.php delete mode 100644 tests_backup/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php delete mode 100644 tests_backup/UnitTest/Mock/Service/MockAuthenticationService.php delete mode 100644 tests_backup/UnitTest/Mock/Service/MockClientIdentificationService.php delete mode 100644 tests_backup/UnitTest/Mock/Service/MockRefreshTokenService.php delete mode 100644 tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTable.php delete mode 100644 tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php delete mode 100644 tests_backup/UnitTest/Mock/Table/MockAccountTable.php delete mode 100644 tests_backup/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php delete mode 100644 tests_backup/UnitTest/Mock/Table/MockAccountTableFailed.php delete mode 100644 tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidator.php delete mode 100644 tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidatorFailed.php diff --git a/composer.json b/composer.json index 67db4f7b..4f1a864f 100644 --- a/composer.json +++ b/composer.json @@ -109,7 +109,6 @@ "development-status": "laminas-development-mode status", "doctrine": "php ./bin/migrations.php", "enable-codestandard": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run", - "functionaltest": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --colors=always --display-phpunit-deprecations --configuration phpunit_functionaltest.xml", "mezzio": "laminas --ansi", "openapi": "php ./vendor/bin/openapi ./src -f json -o ./public/api/docs/swagger.json", "phpcbf": "phpcbf --standard=phpcs.xml -p", @@ -122,7 +121,6 @@ ], "test": [ "@pest" - ], - "unittest": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --colors=always --display-phpunit-deprecations --configuration phpunit_unittest.xml" + ] } } diff --git a/composer.lock b/composer.lock index 78eda2cd..c6d45391 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "brick/math", - "version": "0.14.2", + "version": "0.14.5", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2" + "reference": "618a8077b3c326045e10d5788ed713b341fcfe40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2", - "reference": "55c950aa71a2cabc1d8f2bec1f8a7020bd244aa2", + "url": "https://api.github.com/repos/brick/math/zipball/618a8077b3c326045e10d5788ed713b341fcfe40", + "reference": "618a8077b3c326045e10d5788ed713b341fcfe40", "shasum": "" }, "require": { @@ -56,7 +56,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.2" + "source": "https://github.com/brick/math/tree/0.14.5" }, "funding": [ { @@ -64,7 +64,7 @@ "type": "github" } ], - "time": "2026-01-30T14:03:11+00:00" + "time": "2026-02-03T18:06:51+00:00" }, { "name": "brick/varexporter", @@ -4401,16 +4401,16 @@ }, { "name": "zircote/swagger-php", - "version": "6.0.3", + "version": "6.0.4", "source": { "type": "git", "url": "https://github.com/zircote/swagger-php.git", - "reference": "5d7d7371e9a9349abdc1dc83379774dcf8f72e0c" + "reference": "f0717a52c616291ea6599d241fe5c04bbf7e7ef2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/5d7d7371e9a9349abdc1dc83379774dcf8f72e0c", - "reference": "5d7d7371e9a9349abdc1dc83379774dcf8f72e0c", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/f0717a52c616291ea6599d241fe5c04bbf7e7ef2", + "reference": "f0717a52c616291ea6599d241fe5c04bbf7e7ef2", "shasum": "" }, "require": { @@ -4479,7 +4479,7 @@ ], "support": { "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/6.0.3" + "source": "https://github.com/zircote/swagger-php/tree/6.0.4" }, "funding": [ { @@ -4487,7 +4487,7 @@ "type": "github" } ], - "time": "2026-01-22T03:43:48+00:00" + "time": "2026-02-03T23:31:40+00:00" } ], "packages-dev": [ @@ -6831,28 +6831,28 @@ }, { "name": "phpunit/php-file-iterator", - "version": "5.1.0", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", - "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903", + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -6880,15 +6880,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" } ], - "time": "2024-08-27T05:02:59+00:00" + "time": "2026-02-02T13:52:54+00:00" }, { "name": "phpunit/php-invoker", @@ -7289,12 +7301,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "c4162b6092bc6170cc6d0758ba6ee7d29d0dfbb8" + "reference": "399080a2918c60a3add6eefecfa74f885e1cda2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/c4162b6092bc6170cc6d0758ba6ee7d29d0dfbb8", - "reference": "c4162b6092bc6170cc6d0758ba6ee7d29d0dfbb8", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/399080a2918c60a3add6eefecfa74f885e1cda2f", + "reference": "399080a2918c60a3add6eefecfa74f885e1cda2f", "shasum": "" }, "conflict": { @@ -7404,6 +7416,7 @@ "cesnet/simplesamlphp-module-proxystatistics": "<3.1", "chriskacerguis/codeigniter-restserver": "<=2.7.1", "chrome-php/chrome": "<1.14", + "ci4-cms-erp/ci4ms": "<0.28.5", "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", "ckeditor/ckeditor": "<4.25", "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", @@ -7435,6 +7448,8 @@ "couleurcitron/tarteaucitron-wp": "<0.3", "cpsit/typo3-mailqueue": "<0.4.3|>=0.5,<0.5.1", "craftcms/cms": "<=4.16.16|>=5,<=5.8.20", + "craftcms/commerce": ">=4.0.0.0-RC1-dev,<=4.10|>=5,<=5.5.1", + "craftcms/composer": ">=4.0.0.0-RC1-dev,<=4.10|>=5.0.0.0-RC1-dev,<=5.5.1", "croogo/croogo": "<=4.0.7", "cuyz/valinor": "<0.12", "czim/file-handling": "<1.5|>=2,<2.3", @@ -7452,7 +7467,7 @@ "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", "desperado/xml-bundle": "<=0.1.7", "dev-lancer/minecraft-motd-parser": "<=1.0.5", - "devcode-it/openstamanager": "<=2.9.4", + "devcode-it/openstamanager": "<=2.9.8", "devgroup/dotplant": "<2020.09.14-dev", "digimix/wp-svg-upload": "<=1", "directmailteam/direct-mail": "<6.0.3|>=7,<7.0.3|>=8,<9.5.2", @@ -7535,18 +7550,18 @@ "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1|>=5.3.0.0-beta1,<5.3.5", "ezsystems/ezplatform-graphql": ">=1.0.0.0-RC1-dev,<1.0.13|>=2.0.0.0-beta1,<2.3.12", "ezsystems/ezplatform-http-cache": "<2.3.16", - "ezsystems/ezplatform-kernel": "<1.2.5.1-dev|>=1.3,<1.3.35", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.35", "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", "ezsystems/ezplatform-richtext": ">=2.3,<2.3.26|>=3.3,<3.3.40", "ezsystems/ezplatform-solr-search-engine": ">=1.7,<1.7.12|>=2,<2.0.2|>=3.3,<3.3.15", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": "<6.13.8.2-dev|>=7,<7.5.31", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.31", "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.03.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", "ezyang/htmlpurifier": "<=4.2", "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", - "facturascripts/facturascripts": "<=2025.4|==2025.11|==2025.41|==2025.43", + "facturascripts/facturascripts": "<2025.81", "fastly/magento2": "<1.2.26", "feehi/cms": "<=2.1.1", "feehi/feehicms": "<=2.1.1", @@ -7835,7 +7850,7 @@ "open-web-analytics/open-web-analytics": "<1.8.1", "opencart/opencart": ">=0", "openid/php-openid": "<2.3", - "openmage/magento-lts": "<20.16", + "openmage/magento-lts": "<20.16.1", "opensolutions/vimbadmin": "<=3.0.15", "opensource-workshop/connect-cms": "<1.8.7|>=2,<2.4.7", "orchid/platform": ">=8,<14.43", @@ -7913,7 +7928,7 @@ "prestashop/blockwishlist": ">=2,<2.1.1", "prestashop/contactform": ">=1.0.1,<4.3", "prestashop/gamification": "<2.3.2", - "prestashop/prestashop": "<8.2.3", + "prestashop/prestashop": "<8.2.4|>=9.0.0.0-alpha1,<9.0.3", "prestashop/productcomments": "<5.0.2", "prestashop/ps_checkout": "<4.4.1|>=5,<5.0.5", "prestashop/ps_contactinfo": "<=3.3.2", @@ -7924,6 +7939,7 @@ "processwire/processwire": "<=3.0.246", "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", "propel/propel1": ">=1,<=1.7.1", + "psy/psysh": "<=0.11.22|>=0.12,<=0.12.18", "pterodactyl/panel": "<1.12", "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", "ptrofimov/beanstalk_console": "<1.7.14", @@ -8295,7 +8311,7 @@ "type": "tidelift" } ], - "time": "2026-01-28T22:08:32+00:00" + "time": "2026-02-03T22:10:17+00:00" }, { "name": "sebastian/cli-parser", diff --git a/tests_backup/FunctionalTest/AbstractFunctional.php b/tests_backup/FunctionalTest/AbstractFunctional.php deleted file mode 100644 index 3034adbb..00000000 --- a/tests_backup/FunctionalTest/AbstractFunctional.php +++ /dev/null @@ -1,92 +0,0 @@ -initContainer(); - $this->initApp(); - $this->initPipeline(); - $this->initRoutes(); - } - - public static function tearDownAfterClass(): void - { - system('php ' . dirname(__FILE__) . '/bootstrap.php'); - } - - protected function initContainer(): void - { - $this->container = require __DIR__ . '/../../config/container.php'; - } - - protected function initApp(): void - { - $this->app = $this->container->get(Application::class); - } - - protected function initPipeline(): void - { - $factory = $this->container->get(MiddlewareFactory::class); - (require __DIR__ . '/../../config/pipeline.php')($this->app, $factory, $this->container); - } - - protected function initRoutes(): void - { - $factory = $this->container->get(MiddlewareFactory::class); - (require __DIR__ . '/../../config/routes.php')($this->app, $factory, $this->container); - } - - /** - * Override parent method's hard-coded regex - */ - public static function bodyMatchesJson(array $constraints): Constraint - { - return Assert::logicalAnd( - self::hasHeader( - 'content-type', - Assert::matchesRegularExpression( - ',^application/(.+\+)?json(;.+)?$,' - ) - ), - self::bodyMatches( - Assert::logicalAnd( - Assert::isJson(), - new JsonValueMatchesMany($constraints) - ) - ) - ); - } - - public function resetDatabase(): void - { - system('php ' . dirname(__FILE__) . '/../../bin/migrations.php migrations:sync-metadata-storage --quiet'); - system('php ' . dirname(__FILE__) . '/../../bin/migrations.php migrations:migrate --no-interaction --quiet'); - // phpcs:ignore - system('php ' . dirname(__FILE__) . '/../../bin/migrations.php migrations:migrate Migrations\\\Version20231103223745_CreateAccountTable --no-interaction --quiet'); - system('php ' . dirname(__FILE__) . '/../../bin/migrations.php migrations:migrate --no-interaction --quiet'); - } -} diff --git a/tests_backup/FunctionalTest/Root/Account/AccessTokenHandlerTest.php b/tests_backup/FunctionalTest/Root/Account/AccessTokenHandlerTest.php deleted file mode 100644 index 0f2a61a8..00000000 --- a/tests_backup/FunctionalTest/Root/Account/AccessTokenHandlerTest.php +++ /dev/null @@ -1,272 +0,0 @@ -accountRepository = $this->container->get(AccountRepositoryInterface::class); - $this->accountAccessAuthRepository = $this->container->get(AccountAccessAuthRepository::class); - $this->clientIdentificationService = $this->container->get(ClientIdentificationService::class); - $this->clientIdentificationData = ClientIdentificationData::create( - self::CLIENT_IDENTIFICATION, - self::USER_AGENT - ); - $clientIdentifcationHash = $this->clientIdentificationService->getClientIdentificationHash( - $this->clientIdentificationData - ); - $this->clientIdentification = ClientIdentification::create( - $this->clientIdentificationData, - $clientIdentifcationHash - ); - $this->refreshTokenService = $this->container->get(RefreshTokenService::class); - $this->accessTokenService = $this->container->get(AccessTokenService::class); - $this->refreshToken = $this->refreshTokenService->generate($this->clientIdentification); - /** @var Query $query */ - $query = $this->container->get(Query::class); - $this->PDO = $query->getPdo(); - } - - public function testReturnANewAccessToken(): void - { - $userAccount = $this->accountRepository->findByName('User'); - $accountAccessAuth = new AccountAccessAuth( - null, - $userAccount->id, - 'Testing', - $this->refreshToken->refreshToken, - self::USER_AGENT, - $this->clientIdentificationService->getClientIdentificationHash($this->clientIdentificationData), - new DateTimeImmutable() - ); - $this->accountAccessAuthRepository->insert($accountAccessAuth); - $accountAccessAuthId = (int)$this->PDO->lastInsertId(); - - $request = new ServerRequest( - uri: '/api/token/refresh', - method: 'GET', - headers: [ - 'x-ident' => self::CLIENT_IDENTIFICATION, - 'Authentication' => $this->refreshToken->refreshToken, - 'User-Agent' => self::USER_AGENT, - ] - ); - - $response = $this->app->handle($request); - - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'accessToken' => Assert::isType('string'), - ])); - - $isAccessToken = $this->accessTokenService->isValid($content['accessToken']); - - $this->assertTrue($isAccessToken); - - $this->accountAccessAuthRepository->deleteById($accountAccessAuthId); - } - - public function testGivenRefreshTokenIsInvalid(): void - { - $userAccount = $this->accountRepository->findByName('User'); - $accountAccessAuth = new AccountAccessAuth( - null, - $userAccount->id, - 'Testing', - $this->refreshToken->refreshToken, - self::USER_AGENT, - $this->clientIdentificationService->getClientIdentificationHash($this->clientIdentificationData), - new DateTimeImmutable() - ); - $this->accountAccessAuthRepository->insert($accountAccessAuth); - $accountAccessAuthId = (int)$this->PDO->lastInsertId(); - - $request = new ServerRequest( - uri: '/api/token/refresh', - method: 'GET', - headers: [ - 'x-ident' => self::CLIENT_IDENTIFICATION, - 'Authentication' => self::INVALID_REFRESH_TOKEN, - 'User-Agent' => self::USER_AGENT, - ] - ); - - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::TOKEN_INVALID, $content['message']); - - $this->accountAccessAuthRepository->deleteById($accountAccessAuthId); - } - - public function testGivenRefreshTokenIsExpired(): void - { - $userAccount = $this->accountRepository->findByName('User'); - $accountAccessAuth = new AccountAccessAuth( - 1, - $userAccount->id, - 'Testing', - $this->refreshToken->refreshToken, - self::USER_AGENT, - $this->clientIdentificationService->getClientIdentificationHash($this->clientIdentificationData), - new DateTimeImmutable() - ); - $this->accountAccessAuthRepository->insert($accountAccessAuth); - $accountAccessAuthId = (int)$this->PDO->lastInsertId(); - - $request = new ServerRequest( - uri: '/api/token/refresh', - method: 'GET', - headers: [ - 'x-ident' => self::CLIENT_IDENTIFICATION, - 'Authentication' => self::EXPIRED_REFRESH_TOKEN, - 'User-Agent' => self::USER_AGENT, - ] - ); - - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::TOKEN_INVALID, $content['message']); - - $this->accountAccessAuthRepository->deleteById($accountAccessAuthId); - } - - public function testGivenRefreshTokenIsNotPersistenInDatabase(): void - { - $request = new ServerRequest( - uri: '/api/token/refresh', - method: 'GET', - headers: [ - 'x-ident' => self::CLIENT_IDENTIFICATION, - 'Authentication' => $this->refreshToken->refreshToken, - 'User-Agent' => self::USER_AGENT, - ] - ); - - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::TOKEN_NOT_PERSISTENT, $content['message']); - } - - public function testUnexpectedClientIdentification(): void - { - $userAccount = $this->accountRepository->findByName('User'); - $accountAccessAuth = new AccountAccessAuth( - 1, - $userAccount->id, - 'Testing', - $this->refreshToken->refreshToken, - self::USER_AGENT, - $this->clientIdentificationService->getClientIdentificationHash($this->clientIdentificationData), - new DateTimeImmutable() - ); - $this->accountAccessAuthRepository->insert($accountAccessAuth); - $accountAccessAuthId = (int)$this->PDO->lastInsertId(); - - $request = new ServerRequest( - uri: '/api/token/refresh', - method: 'GET', - headers: [ - 'x-ident' => self::UNEXPECTED_CLIENT_IDENTIFICATION, - 'Authentication' => $this->refreshToken->refreshToken, - 'User-Agent' => self::USER_AGENT, - ] - ); - - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::CLIENT_UNEXPECTED, $content['message']); - - $this->accountAccessAuthRepository->deleteById($accountAccessAuthId); - } - - public function testUnexpectedUserAgent(): void - { - $userAccount = $this->accountRepository->findByName('User'); - $accountAccessAuth = new AccountAccessAuth( - 1, - $userAccount->id, - 'Testing', - $this->refreshToken->refreshToken, - self::USER_AGENT, - $this->clientIdentificationService->getClientIdentificationHash($this->clientIdentificationData), - new DateTimeImmutable() - ); - $this->accountAccessAuthRepository->insert($accountAccessAuth); - $accountAccessAuthId = (int)$this->PDO->lastInsertId(); - - $request = new ServerRequest( - uri: '/api/token/refresh', - method: 'GET', - headers: [ - 'x-ident' => self::CLIENT_IDENTIFICATION, - 'Authentication' => $this->refreshToken->refreshToken, - 'User-Agent' => self::UNEXPECTED_USER_AGENT, - ] - ); - - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - $this->assertSame(IdentityStatusMessage::CLIENT_UNEXPECTED, $content['message']); - - $this->accountAccessAuthRepository->deleteById($accountAccessAuthId); - } -} diff --git a/tests_backup/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php b/tests_backup/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php deleted file mode 100644 index 1e348515..00000000 --- a/tests_backup/FunctionalTest/Root/Account/AccountPasswordForgottenHandlerTest.php +++ /dev/null @@ -1,61 +0,0 @@ -withParsedBody(['email' => self::EMAIL_VALID]); - $response = $this->app->handle($request); - - /** @var AccountRepositoryInterface $accountRepository */ - $accountRepository = $this->container->get(AccountRepositoryInterface::class); - $account = $accountRepository->findByEmail(new EmailType(self::EMAIL_VALID)); - - /** @var TokenRepositoryInterface $tokenRepository */ - $tokenRepository = $this->container->get(TokenRepositoryInterface::class); - - $token = $tokenRepository->findByAccountId($account->id); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - $this->assertArrayHasKey(0, $token); - $this->assertInstanceOf(UuidInterface::class, $token[0]->token); - } - - public function testDontCreateTokenForPasswordChange(): void - { - $request = new ServerRequest( - uri: '/api/account/password/forgotten', - method: 'POST' - ); - $request = $request->withParsedBody(['email' => self::EMAIL_INVALID]); - $response = $this->app->handle($request); - - /** @var AccountRepositoryInterface $accountRepository */ - $accountRepository = $this->container->get(AccountRepositoryInterface::class); - $account = $accountRepository->findByEmail(new EmailType(self::EMAIL_INVALID)); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - $this->assertNull($account); - } -} diff --git a/tests_backup/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php b/tests_backup/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php deleted file mode 100644 index 9c93510f..00000000 --- a/tests_backup/FunctionalTest/Root/Account/AccountPasswordHandlerTest.php +++ /dev/null @@ -1,134 +0,0 @@ -accountRepository = $this->container->get(AccountRepositoryInterface::class); - $this->tokenRepository = $this->container->get(TokenRepositoryInterface::class); - $this->uuid = $this->container->get(UuidFactoryInterface::class); - - $this->account = $this->accountRepository->findByEmail(new EmailType('user@example.com')); - $this->token = new Token( - null, - $this->account->id, - TokenType::EMail, - $this->uuid->uuid7(), - new DateTimeImmutable() - ); - } - - public function testChangePasswortHasStatusOk(): void - { - $this->tokenRepository->insert($this->token); - - $request = new ServerRequest( - uri: '/api/account/password/' . $this->token->token->toString(), - method: 'PATCH' - ); - $request = $request->withParsedBody(['password' => self::PASSWORD_NEW]); - $response = $this->app->handle($request); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - } - - public function testChangedPasswordIsValid(): void - { - $this->tokenRepository->insert($this->token); - - $request = new ServerRequest( - uri: '/api/account/password/' . $this->token->token->toString(), - method: 'PATCH' - ); - $request = $request->withParsedBody(['password' => self::PASSWORD_NEW]); - $this->app->handle($request); - - $changedAccount = $this->accountRepository->findById($this->account->id); - - $this->assertNotSame($this->account->password, $changedAccount->password); - $this->assertTrue(password_verify(self::PASSWORD_NEW, $changedAccount->password)); - } - - public function testChangedPasswordIsInvalid(): void - { - $this->tokenRepository->insert($this->token); - - $request = new ServerRequest( - uri: '/api/account/password/' . $this->token->token->toString(), - method: 'PATCH' - ); - $request = $request->withParsedBody(['password' => self::PASSWORD_NEW_INVALID]); - $response = $this->app->handle($request); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - } - - public function testTokenIsInvalid(): void - { - $request = new ServerRequest( - uri: '/api/account/password/InvalidToken', - method: 'PATCH' - ); - $request = $request->withParsedBody(['password' => self::PASSWORD_NEW]); - $response = $this->app->handle($request); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - } - - public function testTokenIsMissed(): void - { - $request = new ServerRequest( - uri: '/api/account/password/', - method: 'PATCH' - ); - $request = $request->withParsedBody(['password' => self::PASSWORD_NEW]); - $response = $this->app->handle($request); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - } - - public function testTokenWasDestroyed(): void - { - $this->tokenRepository->insert($this->token); - - $request = new ServerRequest( - uri: '/api/account/password/' . $this->token->token->toString(), - method: 'PATCH' - ); - $request = $request->withParsedBody(['password' => self::PASSWORD_NEW]); - $this->app->handle($request); - - $destroyedToken = $this->tokenRepository->findByToken($this->token->token->toString()); - - $this->assertNull($destroyedToken); - } -} diff --git a/tests_backup/FunctionalTest/Root/PingHandlerTest.php b/tests_backup/FunctionalTest/Root/PingHandlerTest.php deleted file mode 100644 index 7c861301..00000000 --- a/tests_backup/FunctionalTest/Root/PingHandlerTest.php +++ /dev/null @@ -1,29 +0,0 @@ -app->handle($request); - - $this->assertSame($response->getStatusCode(), HTTP::STATUS_OK); - $this->assertThat($response, $this->bodyMatchesJson([ - 'ack' => Assert::greaterThanOrEqual($timestamp), - ])); - } -} diff --git a/tests_backup/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php b/tests_backup/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php deleted file mode 100644 index 01889599..00000000 --- a/tests_backup/FunctionalTest/Root/Workspace/ListOwnWorkspacesHandlerTest.php +++ /dev/null @@ -1,97 +0,0 @@ -uuid = $this->container->get(UuidFactoryInterface::class); - - $accountRepository = $this->container->get(AccountRepositoryInterface::class); - - $account = new Account( - null, - $this->uuid->uuid7(), - 'I see your Token', - password_hash('I see your Token', PASSWORD_DEFAULT), - new EmailType('iseeyourtoken@example.com'), - new DateTimeImmutable(), - new DateTimeImmutable() - ); - - $accountRepository->insert($account); - - $request = new ServerRequest( - uri: '/api/account/authentication', - method: 'POST' - ); - $request = $request->withParsedBody( - ['email' => $account->email->toString(), 'password' => 'I see your Token'] - ); - - $response = $this->app->handle($request); - - $content = $this->getContentAsJson($response); - - $this->accessToken = $content['accessToken']; - } - - public function tearDown(): void - { - parent::tearDown(); - $this->resetDatabase(); - } - - public function testAuthorizationMissed(): void - { - $request = new ServerRequest( - uri: '/api/me/workspaces', - method: 'GET', - ); - - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - $this->assertSame(WorkspaceStatusMessage::UNAUTHORIZED_ACCESS, $content['message']); - } - - public function testStatusOk(): void - { - $request = new ServerRequest( - uri: '/api/me/workspaces', - method: 'GET', - headers: ['Authorization' => $this->accessToken], - ); - - $response = $this->app->handle($request); - - $this->assertSame(HTTP::STATUS_OK, $response->getStatusCode()); - } -} diff --git a/tests_backup/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php b/tests_backup/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php deleted file mode 100644 index d26727f3..00000000 --- a/tests_backup/FunctionalTest/Root/Workspace/WorkspaceCreateHandlerTest.php +++ /dev/null @@ -1,175 +0,0 @@ -uuid */ - $this->uuid = $this->container->get(UuidFactoryInterface::class); - - /** @var AccountRepositoryInterface $accountRepository */ - $accountRepository = $this->container->get(AccountRepositoryInterface::class); - /** @var UuidFactoryInterface $uuid */ - - $account = new Account( - null, - $this->uuid->uuid7(), - 'I see your Token', - password_hash('I see your Token', PASSWORD_DEFAULT), - new EmailType('iseeyourtoken@example.com'), - new DateTimeImmutable(), - new DateTimeImmutable() - ); - - $accountRepository->insert($account); - - $request = new ServerRequest( - uri: '/api/account/authentication', - method: 'POST' - ); - $request = $request->withParsedBody( - ['email' => $account->email->toString(), 'password' => 'I see your Token'] - ); - - $response = $this->app->handle($request); - - $content = $this->getContentAsJson($response); - - $this->accessToken = $content['accessToken']; - } - - public function tearDown(): void - { - parent::tearDown(); - $this->resetDatabase(); - } - - public function testBodyIsEmpty(): void - { - $request = new ServerRequest( - uri: '/api/workspace', - method: 'POST', - headers: ['Authorization' => $this->accessToken], - ); - - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(WorkspaceStatusMessage::INVALID_WORKSPACE_NAME, $content['message']); - } - - public function testBodyHasInvalidParameter(): void - { - $request = new ServerRequest( - uri: '/api/workspace', - method: 'POST', - headers: ['Authorization' => $this->accessToken], - ); - $request = $request->withParsedBody(['name' => 'Das ist Türlicht falsch']); - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_BAD_REQUEST, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(WorkspaceStatusMessage::INVALID_WORKSPACE_NAME, $content['message']); - } - - public function testAuthorizationMissed(): void - { - $request = new ServerRequest( - uri: '/api/workspace', - method: 'POST', - ); - $request = $request->withParsedBody(['name' => 'Das ist Türlicht falsch']); - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_UNAUTHORIZED, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(WorkspaceStatusMessage::UNAUTHORIZED_ACCESS, $content['message']); - } - - public function testWorkspaceAlreadyInUse(): void - { - $workspaceRepository = $this->container->get(WorkspaceRepositoryInterface::class); - - $workspace = new Workspace( - id: null, - uuid: $this->uuid->uuid7(), - accountId: 1, - name: 'Duplicated Entry', - slug: 'duplicated-entry', - description: 'My own workspace is so wonderfully', - ); - - $workspaceRepository->insert($workspace); - - $request = new ServerRequest( - uri: '/api/workspace', - method: 'POST', - headers: ['Authorization' => $this->accessToken], - ); - $request = $request->withParsedBody(['name' => 'Duplicated Entry']); - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_CONFLICT, $response->getStatusCode()); - $this->assertThat($response, $this->bodyMatchesJson([ - 'statusCode' => Assert::isType(DataType::INTEGER->value), - 'message' => Assert::isType(DataType::STRING->value), - ])); - $this->assertSame(WorkspaceStatusMessage::DUPLICATED_WORKSPACE_NAME, $content['message']); - } - - public function testWorkspaceWasCreated(): void - { - $request = new ServerRequest( - uri: '/api/workspace', - method: 'POST', - headers: ['Authorization' => $this->accessToken], - ); - $request = $request->withParsedBody(['name' => 'Created Workspace']); - $response = $this->app->handle($request); - $content = $this->getContentAsJson($response); - - $this->assertSame(HTTP::STATUS_CREATED, $response->getStatusCode()); - $this->assertSame('/api/workspace/created-workspace', $response->getHeaderLine('Location')); - $this->assertSame('Created Workspace', $content['name']); - $this->assertSame('created-workspace', $content['slug']); - } -} diff --git a/tests_backup/FunctionalTest/bootstrap.php b/tests_backup/FunctionalTest/bootstrap.php deleted file mode 100644 index aba6b5ec..00000000 --- a/tests_backup/FunctionalTest/bootstrap.php +++ /dev/null @@ -1,10 +0,0 @@ -addSql($sql); - } - - public function down(Schema $schema): void - { - $sql = <<addSql($sql); - } -} diff --git a/tests_backup/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php b/tests_backup/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php deleted file mode 100644 index f3b69052..00000000 --- a/tests_backup/FunctionalTest/database/migrations/Version20990921210157_InsertWorkspaceTestData.php +++ /dev/null @@ -1,32 +0,0 @@ -addSql($sql); - } - - public function down(Schema $schema): void - { - $sql = <<addSql($sql); - } -} diff --git a/tests_backup/UnitTest/AppTest/Handler/AbstractTestHandler.php b/tests_backup/UnitTest/AppTest/Handler/AbstractTestHandler.php deleted file mode 100644 index 9a1c05a8..00000000 --- a/tests_backup/UnitTest/AppTest/Handler/AbstractTestHandler.php +++ /dev/null @@ -1,24 +0,0 @@ -request = new MockServerRequest(); - - parent::setUp(); - } -} diff --git a/tests_backup/UnitTest/AppTest/Handler/PingHandlerTest.php b/tests_backup/UnitTest/AppTest/Handler/PingHandlerTest.php deleted file mode 100644 index f2151e00..00000000 --- a/tests_backup/UnitTest/AppTest/Handler/PingHandlerTest.php +++ /dev/null @@ -1,29 +0,0 @@ -handle( - $this->createMock(ServerRequestInterface::class) - ); - - $json = json_decode((string)$response->getBody(), null, 512, JSON_THROW_ON_ERROR); - - self::assertInstanceOf(JsonResponse::class, $response); - self::assertTrue(property_exists($json, 'ack') && $json->ack !== null); - } -} diff --git a/tests_backup/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php b/tests_backup/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php deleted file mode 100644 index 799d8eb0..00000000 --- a/tests_backup/UnitTest/AppTest/Hydrator/AccountAccessAuthHydratorTest.php +++ /dev/null @@ -1,55 +0,0 @@ -hydrate(AccountAccessAuth::VALID_DATA); - - $this->assertInstanceOf(AccountAccessAuthInterface::class, $account); - $this->assertSame(AccountAccessAuth::ID, $account->id); - } - - public function testCanHydrateAccountAccessAuthCollection(): void - { - $hydrator = new AccountAccessAuthHydrator(); - - $accounts = $hydrator->hydrateCollection([AccountAccessAuth::VALID_DATA]); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $accounts); - $this->assertInstanceOf(AccountAccessAuthInterface::class, $accounts[0]); - $this->assertSame(AccountAccessAuth::ID, $accounts[0]->id); - } - - public function testCanExtractAccountAccessAuth(): void - { - $hydrator = new AccountAccessAuthHydrator(); - - $account = $hydrator->hydrate(AccountAccessAuth::VALID_DATA); - $account = $hydrator->extract($account); - - $this->assertIsArray($account); - $this->assertSame(AccountAccessAuth::VALID_DATA, $account); - } - - public function testCanExtractAccountAccessAuthCollection(): void - { - $hydrator = new AccountAccessAuthHydrator(); - $accounts = $hydrator->hydrateCollection([AccountAccessAuth::VALID_DATA]); - $accounts = $hydrator->extractCollection($accounts); - - $this->assertIsArray($accounts); - $this->assertArrayHasKey(0, $accounts); - $this->assertSame(AccountAccessAuth::VALID_DATA, $accounts[0]); - } -} diff --git a/tests_backup/UnitTest/AppTest/Hydrator/AccountHydratorTest.php b/tests_backup/UnitTest/AppTest/Hydrator/AccountHydratorTest.php deleted file mode 100644 index 3987a6bc..00000000 --- a/tests_backup/UnitTest/AppTest/Hydrator/AccountHydratorTest.php +++ /dev/null @@ -1,66 +0,0 @@ -uuidFactory = new UuidFactory(); - } - - public function testCanHydrateAccount(): void - { - $hydrator = new AccountHydrator($this->uuidFactory); - - $account = $hydrator->hydrate(Account::VALID_DATA); - - $this->assertInstanceOf(AccountInterface::class, $account); - $this->assertSame(Account::ID, $account->id); - } - - public function testCanHydrateAccountCollection(): void - { - $hydrator = new AccountHydrator($this->uuidFactory); - - /** @var AccountInterface[] $accounts | [] */ - $accounts = $hydrator->hydrateCollection([Account::VALID_DATA]); - - $this->assertInstanceOf(AccountCollectionInterface::class, $accounts); - $this->assertInstanceOf(AccountInterface::class, $accounts[0]); - $this->assertSame(Account::ID, $accounts[0]->id); - } - - public function testCanExtractAccount(): void - { - $hydrator = new AccountHydrator($this->uuidFactory); - - $account = $hydrator->hydrate(Account::VALID_DATA); - $account = $hydrator->extract($account); - - $this->assertIsArray($account); - $this->assertSame(Account::VALID_DATA, $account); - } - - public function testCanExtractAccountCollection(): void - { - $hydrator = new AccountHydrator($this->uuidFactory); - $accounts = $hydrator->hydrateCollection([Account::VALID_DATA]); - $accounts = $hydrator->extractCollection($accounts); - - $this->assertIsArray($accounts); - $this->assertArrayHasKey(0, $accounts); - $this->assertSame(Account::VALID_DATA, $accounts[0]); - } -} diff --git a/tests_backup/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php b/tests_backup/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php deleted file mode 100644 index cdd34f8b..00000000 --- a/tests_backup/UnitTest/AppTest/Middleware/AbstractTestMiddleware.php +++ /dev/null @@ -1,28 +0,0 @@ -request = new MockServerRequest(); - $this->handler = new MockRequestHandler(); - - parent::setUp(); - } -} diff --git a/tests_backup/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php deleted file mode 100644 index 60d75413..00000000 --- a/tests_backup/UnitTest/AppTest/Middleware/AccountAccessAuthPersistMiddlewareTest.php +++ /dev/null @@ -1,108 +0,0 @@ -repository = new MockAccountAccessAuthRepository(); - $this->hydrator = new AccountHydrator(new UuidFactory()); - } - - public function testCanPersistAccountAccessAuth(): void - { - $middleware = new PersistAuthenticationMiddleware($this->repository); - $account = $this->hydrator->hydrate(Account::VALID_DATA); - $clientData = ClientIdentificationData::create('1', 'default'); - $clientIdent = ClientIdentification::create($clientData, '1234'); - $refreshToken = RefreshToken::fromString('1234'); - - $request = $this->request->withAttribute(AccountInterface::AUTHENTICATED, $account) - ->withAttribute(ClientIdentification::class, $clientIdent) - ->withAttribute(RefreshToken::class, $refreshToken); - - $response = $middleware->process($request, $this->handler); - - $this->assertNotInstanceOf(JsonResponse::class, $response); - } - - public function testFindMissingAccountEntity(): void - { - $middleware = new PersistAuthenticationMiddleware($this->repository); - - $clientData = ClientIdentificationData::create('1', 'default'); - $clientIdent = ClientIdentification::create($clientData, '1234'); - $refreshToken = RefreshToken::fromString('1234'); - - $request = $this->request->withAttribute(ClientIdentification::class, $clientIdent) - ->withAttribute(RefreshToken::class, $refreshToken); - - $this->expectException(HttpUnauthorizedException::class); - $middleware->process($request, $this->handler); - } - - public function testFindMissingClientIdentification(): void - { - $middleware = new PersistAuthenticationMiddleware($this->repository); - - $account = $this->hydrator->hydrate(Account::VALID_DATA); - $refreshToken = RefreshToken::fromString('1234'); - - $request = $this->request->withAttribute(AccountInterface::AUTHENTICATED, $account) - ->withAttribute(RefreshToken::class, $refreshToken); - - $this->expectException(HttpUnauthorizedException::class); - $middleware->process($request, $this->handler); - } - - public function testFindMissingRefreshToken(): void - { - $middleware = new PersistAuthenticationMiddleware($this->repository); - - $account = $this->hydrator->hydrate(Account::VALID_DATA); - $clientData = ClientIdentificationData::create('1', 'default'); - $clientIdent = ClientIdentification::create($clientData, '1234'); - - $request = $this->request->withAttribute(AccountInterface::AUTHENTICATED, $account) - ->withAttribute(ClientIdentification::class, $clientIdent); - - $this->expectException(HttpUnauthorizedException::class); - $middleware->process($request, $this->handler); - } - - public function testAccountAccessAuthHasDuplicat(): void - { - $middleware = new PersistAuthenticationMiddleware($this->repository); - $account = $this->hydrator->hydrate(Account::INVALID_DATA); - $clientData = ClientIdentificationData::create('1', 'default'); - $clientIdent = ClientIdentification::create($clientData, '1234'); - $refreshToken = RefreshToken::fromString('1234'); - - $request = $this->request->withAttribute(AccountInterface::AUTHENTICATED, $account) - ->withAttribute(ClientIdentification::class, $clientIdent) - ->withAttribute(RefreshToken::class, $refreshToken); - - $this->expectException(HttpDuplicateEntryException::class); - $middleware->process($request, $this->handler); - } -} diff --git a/tests_backup/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php deleted file mode 100644 index cdc893be..00000000 --- a/tests_backup/UnitTest/AppTest/Middleware/AccountAuthenticationMiddlewareTest.php +++ /dev/null @@ -1,107 +0,0 @@ -accessTokenService = new MockAccessTokenService(); - $this->accountRepository = new MockAccountRepository(); - $this->logger = new NullLogger(); - $this->uuidFactory = new UuidFactory(); - } - - public function testAccountAuthenticatedIsGuest(): void - { - $middleware = new RequestAuthenticationMiddleware( - $this->accessTokenService, - $this->accountRepository, - $this->uuidFactory, - $this->logger, - ); - $handler = new MockAccountAuthenticationMiddlewareRequestHandler(); - $response = $middleware->process($this->request, $handler); - $header = $response->getHeaderLine('Authorization'); - - $this->assertInstanceOf(ResponseInterface::class, $response); - $this->assertNotInstanceOf(JsonResponse::class, $response); - $this->assertSame('', $header); - } - - public function testAccountSuccessfulAuthenticated(): void - { - $accessToken = $this->accessTokenService->generate($this->uuidFactory->fromString(Account::UUID)); - $request = $this->request->withHeader('Authorization', $accessToken); - - $middleware = new RequestAuthenticationMiddleware( - $this->accessTokenService, - $this->accountRepository, - $this->uuidFactory, - $this->logger, - ); - - $handler = new MockAccountAuthenticationMiddlewareRequestHandler(); - $response = $middleware->process($request, $handler); - $header = $response->getHeaderLine('Authorization'); - - $this->assertNotInstanceOf(JsonResponse::class, $response); - $this->assertSame('true', $header); - } - - public function testTokenHasExpired(): void - { - $accessTokenService = new MockAccessTokenServiceWithoutDuration(); - $accessToken = $accessTokenService->generate($this->uuidFactory->fromString(Account::UUID)); - $request = $this->request->withHeader('Authorization', $accessToken); - - $middleware = new RequestAuthenticationMiddleware( - $this->accessTokenService, - $this->accountRepository, - $this->uuidFactory, - $this->logger, - ); - - $this->expectException(HttpUnauthorizedException::class); - $middleware->process($request, $this->handler); - } - - public function testTokenHasInvalid(): void - { - $accessToken = $this->accessTokenService->generate($this->uuidFactory->fromString(Account::UUID)); - $request = $this->request->withHeader('Authorization', $accessToken); - $accountRepository = new MockAccountRepositoryAccountAuthenticationMiddlewareInvalidToken(); - $middleware = new RequestAuthenticationMiddleware( - $this->accessTokenService, - $accountRepository, - $this->uuidFactory, - $this->logger, - ); - - $this->expectException(HttpUnauthorizedException::class); - $middleware->process($request, $this->handler); - } -} diff --git a/tests_backup/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php deleted file mode 100644 index a9ccf18d..00000000 --- a/tests_backup/UnitTest/AppTest/Middleware/AuthenticationConditionsMiddlewareTest.php +++ /dev/null @@ -1,42 +0,0 @@ -middleware = new AuthenticationConditionsMiddleware(); - } - - public function testIsSuccessfully(): void - { - $response = $this->middleware->process($this->request, $this->handler); - - $this->assertInstanceOf(ResponseInterface::class, $response); - } - - public function testRequestIsAuthenticated(): void - { - $request = $this->request->withHeader('Authentication', []); - - $this->expectException(HttpUnauthorizedException::class); - $this->middleware->process($request, $this->handler); - } - - public function testRequestIsAuthorized(): void - { - $request = $this->request->withHeader('Authorization', []); - - $this->expectException(HttpUnauthorizedException::class); - $this->middleware->process($request, $this->handler); - } -} diff --git a/tests_backup/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php deleted file mode 100644 index 91cbb8bd..00000000 --- a/tests_backup/UnitTest/AppTest/Middleware/AuthenticationValidationMiddlewareTest.php +++ /dev/null @@ -1,33 +0,0 @@ -process($this->request, $this->handler); - - $this->assertNotInstanceOf(JsonResponse::class, $response); - } - - public function testValidationFailed(): void - { - $middleware = new AuthenticationValidationMiddleware( - new MockAuthenticationValidatorFailed(), - ); - - $this->expectException(HttpUnauthorizedException::class); - $middleware->process($this->request, $this->handler); - } -} diff --git a/tests_backup/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php deleted file mode 100644 index 81254821..00000000 --- a/tests_backup/UnitTest/AppTest/Middleware/ClientIdentificationMiddlewareTest.php +++ /dev/null @@ -1,36 +0,0 @@ -middleware = new ClientIdentificationMiddleware( - new MockClientIdentificationService(), - ); - } - - public function testGenerateClientIdentification(): void - { - $request = $this->request->withHeader('x-ident', '1') - ->withHeader('user-agent', 'Test Browser Agent'); - - $response = $this->middleware->process($request, $this->handler); - - $this->assertInstanceOf(ResponseInterface::class, $response); - $this->assertNotInstanceOf(JsonResponse::class, $response); - } - - // ToDo Create test for error cases -} diff --git a/tests_backup/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php deleted file mode 100644 index d01a3805..00000000 --- a/tests_backup/UnitTest/AppTest/Middleware/GenerateAccessTokenMiddlewareTest.php +++ /dev/null @@ -1,34 +0,0 @@ -middleware = new GenerateAccessTokenMiddleware( - new MockAccessTokenService() - ); - } - - public function testCanGenerateAccessToken(): void - { - $request = $this->request->withAttribute(AccountInterface::AUTHENTICATED, new MockAccount()); - $response = $this->middleware->process($request, $this->handler); - - $this->assertInstanceOf(ResponseInterface::class, $response); - $this->assertNotInstanceOf(JsonResponse::class, $response); - } -} diff --git a/tests_backup/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php b/tests_backup/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php deleted file mode 100644 index 6422b1a1..00000000 --- a/tests_backup/UnitTest/AppTest/Middleware/GenerateRefreshTokenMiddlewareTest.php +++ /dev/null @@ -1,39 +0,0 @@ -middleware = new GenerateRefreshTokenMiddleware( - new MockRefreshTokenService() - ); - } - - public function testCanGenerateRefreshToken(): void - { - $data = ClientIdentification::create( - ClientIdentificationData::create(null, 'defaul'), - '1' - ); - - $request = $this->request->withAttribute(ClientIdentification::class, $data); - $response = $this->middleware->process($request, $this->handler); - - $this->assertInstanceOf(ResponseInterface::class, $response); - $this->assertNotInstanceOf(JsonResponse::class, $response); - } -} diff --git a/tests_backup/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php b/tests_backup/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php deleted file mode 100644 index 2eaddde8..00000000 --- a/tests_backup/UnitTest/AppTest/Repository/AccountAccessAuthRepositoryTest.php +++ /dev/null @@ -1,194 +0,0 @@ -repository = new AccountAccessAuthRepository(new MockAccountAccessAuthTable()); - $this->hydrator = new AccountAccessAuthHydrator(); - } - - public function testCanInsertAccountAccessAuth(): void - { - $result = $this->repository->insert($this->hydrator->hydrate(AccountAccessAuth::VALID_DATA)); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testInsertAccountAccessAuthThrowDuplicateEntryException(): void - { - $this->expectException(DuplicateEntryException::class); - - $this->repository->insert($this->hydrator->hydrate(AccountAccessAuth::INVALID_DATA)); - } - - public function testCanUpdateAccountAccessAuth(): void - { - $result = $this->repository->update($this->hydrator->hydrate(AccountAccessAuth::VALID_DATA)); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testUpdateAccountAccessAuthThrowInvalidArgumentException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->repository->update($this->hydrator->hydrate(AccountAccessAuth::INVALID_DATA)); - } - - public function testCanDeleteById(): void - { - $result = $this->repository->deleteById(AccountAccessAuth::ID); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testDeleteByIdThrowInvalidArgumentException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->repository->deleteById(AccountAccessAuth::ID_INVALID); - } - - public function testCanFindById(): void - { - $result = $this->repository->findById(AccountAccessAuth::ID); - - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result); - $this->assertSame(AccountAccessAuth::VALID_DATA, $this->hydrator->extract($result)); - } - - public function testFindByIdIsEmpty(): void - { - $result = $this->repository->findById(AccountAccessAuth::ID_INVALID); - - $this->assertNull($result); - } - - public function testCanFindByUserId(): void - { - $result = $this->repository->findByAccountId(AccountAccessAuth::USER_ID); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result[0]); - $this->assertSame([0 => AccountAccessAuth::VALID_DATA], $this->hydrator->extractCollection($result)); - } - - public function testFindByUserIdIsEmpty(): void - { - $result = $this->repository->findByAccountId(AccountAccessAuth::USER_ID_INVALID); - - $this->assertInstanceOf(AccountAccessAuthCollection::class, $result); - $this->assertEmpty($result); - } - - public function testCanFindByLabel(): void - { - $result = $this->repository->findByLabel(AccountAccessAuth::LABEL); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result[0]); - $this->assertSame([0 => AccountAccessAuth::VALID_DATA], $this->hydrator->extractCollection($result)); - } - - public function testFindByLabelIsEmpty(): void - { - $result = $this->repository->findByLabel(AccountAccessAuth::LABEL_INVALID); - - $this->assertInstanceOf(AccountAccessAuthCollection::class, $result); - $this->assertEmpty($result); - } - - public function testCanFindByRefreshToken(): void - { - $result = $this->repository->findByRefreshToken(AccountAccessAuth::REFRESH_TOKEN); - - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result); - $this->assertSame(AccountAccessAuth::VALID_DATA, $this->hydrator->extract($result)); - } - - public function testFindByRefreshTokenIsEmpty(): void - { - $result = $this->repository->findByRefreshToken(AccountAccessAuth::REFRESH_TOKEN_INVALID); - - $this->assertNull($result); - } - - public function testCanFindByUserAgent(): void - { - $result = $this->repository->findByUserAgent(AccountAccessAuth::USER_AGENT); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result[0]); - $this->assertSame([0 => AccountAccessAuth::VALID_DATA], $this->hydrator->extractCollection($result)); - } - - public function testCanFindByUserAgentIsEmpty(): void - { - $result = $this->repository->findByUserAgent(AccountAccessAuth::USER_AGENT_INVALID); - - $this->assertInstanceOf(AccountAccessAuthCollection::class, $result); - $this->assertEmpty($result); - } - - public function testCanFindByClientIdentHash(): void - { - $result = $this->repository->findByClientIdentHash(AccountAccessAuth::CLIENT_IDENT_HASH); - - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result); - $this->assertSame(AccountAccessAuth::VALID_DATA, $this->hydrator->extract($result)); - } - - public function testFindByClientIdentHashIsEmpty(): void - { - $result = $this->repository->findByClientIdentHash(AccountAccessAuth::CLIENT_IDENT_HASH_INVALID); - - $this->assertNull($result); - } - - public function testCanFindAll(): void - { - $result = $this->repository->findAll(); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result[0]); - $this->assertSame([0 => AccountAccessAuth::VALID_DATA], $this->hydrator->extractCollection($result)); - } - - public function testFindAllIsEmpty(): void - { - $repository = new AccountAccessAuthRepository(new MockAccountAccessAuthTableFailed()); - - $result = $repository->findAll(); - - $this->assertInstanceOf(AccountAccessAuthCollection::class, $result); - $this->assertEmpty($result); - } -} diff --git a/tests_backup/UnitTest/AppTest/Repository/AccountRepositoryTest.php b/tests_backup/UnitTest/AppTest/Repository/AccountRepositoryTest.php deleted file mode 100644 index 20eaaad5..00000000 --- a/tests_backup/UnitTest/AppTest/Repository/AccountRepositoryTest.php +++ /dev/null @@ -1,161 +0,0 @@ -uuidFactory = new UuidFactory(); - $this->repository = new AccountRepository(new MockAccountTable()); - $this->hydrator = new AccountHydrator($this->uuidFactory); - } - - public function testCanInsertAccount(): void - { - $result = $this->repository->insert($this->hydrator->hydrate(Account::VALID_DATA)); - - $this->assertIsInt($result); - $this->assertSame(Account::ID, $result); - } - - public function testInsertAccountThrowsException(): void - { - $this->expectException(DuplicateEntryException::class); - - $this->repository->insert($this->hydrator->hydrate(Account::INVALID_DATA)); - } - - public function testCanUpdateAccount(): void - { - $result = $this->repository->update($this->hydrator->hydrate(Account::VALID_DATA)); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testUpdateAccountThrowsException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->repository->update($this->hydrator->hydrate(Account::INVALID_DATA)); - } - - public function testCanDeleteAccountById(): void - { - $result = $this->repository->deleteById(Account::ID); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testDeleteAccountByIdThrowsInvalidArgumentException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->repository->deleteById(Account::ID_INVALID); - } - - public function testCanFindById(): void - { - $result = $this->repository->findById(Account::ID); - - $this->assertInstanceOf(AccountInterface::class, $result); - $this->assertSame(Account::VALID_DATA, $this->hydrator->extract($result)); - } - - public function testFindByIdIsEmpty(): void - { - $result = $this->repository->findById(Account::ID_INVALID); - - $this->assertNull($result); - } - - public function testCanFindByUuid(): void - { - $uuid = $this->uuidFactory->fromString(Account::UUID); - $result = $this->repository->findByUuid($uuid); - - $this->assertInstanceOf(AccountInterface::class, $result); - $this->assertSame(Account::VALID_DATA, $this->hydrator->extract($result)); - } - - public function testFindByUuidIsEmtpy(): void - { - $uuid = $this->uuidFactory->fromString(Account::UUID_INVALID); - - $result = $this->repository->findByUuid($uuid); - - $this->assertNull($result); - } - - public function testCanFindByName(): void - { - $result = $this->repository->findByName(Account::NAME); - - $this->assertInstanceOf(AccountInterface::class, $result); - $this->assertSame(Account::VALID_DATA, $this->hydrator->extract($result)); - } - - public function testFindByNameIsEmpty(): void - { - $result = $this->repository->findByName(Account::NAME_INVALID); - - $this->assertNull($result); - } - - public function testCanFindByEmail(): void - { - $result = $this->repository->findByEmail(new EmailType(Account::EMAIL)); - - $this->assertInstanceOf(AccountInterface::class, $result); - $this->assertSame(Account::VALID_DATA, $this->hydrator->extract($result)); - } - - public function testFindByEmailIsEmpty(): void - { - $result = $this->repository->findByEmail(new EmailType(Account::EMAIL_INVALID)); - - $this->assertNull($result); - } - - public function testCanFindAll(): void - { - $result = $this->repository->findAll(); - - $this->assertInstanceOf(AccountCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertInstanceOf(AccountInterface::class, $result[0]); - $this->assertSame([0 => Account::VALID_DATA], $this->hydrator->extractCollection($result)); - } - - public function testFindAllIsEmpty(): void - { - $repository = new AccountRepository(new MockAccountTableFailed()); - - $result = $repository->findAll(); - - $this->assertInstanceOf(AccountCollectionInterface::class, $result); - $this->assertEmpty($result); - } -} diff --git a/tests_backup/UnitTest/AppTest/Service/AccessTokenServiceTest.php b/tests_backup/UnitTest/AppTest/Service/AccessTokenServiceTest.php deleted file mode 100644 index 9361e32c..00000000 --- a/tests_backup/UnitTest/AppTest/Service/AccessTokenServiceTest.php +++ /dev/null @@ -1,48 +0,0 @@ -account = new MockAccount(); - } - - public function testGenerateValidAccessToken(): void - { - $config = Token::getTokenStruct(); - $jwtTokenConfig = JwtTokenConfig::createFromArray($config); - - $service = new AccessTokenService($jwtTokenConfig); - - $token = $service->generate($this->account->uuid); - - $isValid = $service->isValid($token); - - $this->assertTrue($isValid); - } - - public function testGenerateValidAccessTokenFails(): void - { - $config = Token::getTokenStruct(); - $config['algorithmus'] = ''; - $jwtTokenConfig = JwtTokenConfig::createFromArray($config); - - $service = new AccessTokenService($jwtTokenConfig); - - $this->expectException(DomainException::class); - - $service->generate($this->account->uuid); - } -} diff --git a/tests_backup/UnitTest/AppTest/Service/AuthenticationServiceTest.php b/tests_backup/UnitTest/AppTest/Service/AuthenticationServiceTest.php deleted file mode 100644 index 0d15d14c..00000000 --- a/tests_backup/UnitTest/AppTest/Service/AuthenticationServiceTest.php +++ /dev/null @@ -1,31 +0,0 @@ -service = new AuthenticationService(); - } - - public function testPasswordComparisonIsSuccessful(): void - { - $compare = $this->service->isPasswordMatch(Account::PASSWORD_STRING, Account::PASSWORD); - - $this->assertTrue($compare); - } - - public function testPasswordComparisonFails(): void - { - $compare = $this->service->isPasswordMatch(Account::PASSWORD_STRING, Account::PASSWORD_INVALID); - - $this->assertFalse($compare); - } -} diff --git a/tests_backup/UnitTest/AppTest/Service/RefreshTokenServiceTest.php b/tests_backup/UnitTest/AppTest/Service/RefreshTokenServiceTest.php deleted file mode 100644 index c01d685d..00000000 --- a/tests_backup/UnitTest/AppTest/Service/RefreshTokenServiceTest.php +++ /dev/null @@ -1,51 +0,0 @@ -client = ClientIdentification::create( - ClientIdentificationData::create(null, 'default'), - '1' - ); - } - - public function testGenerateValidRefreshToken(): void - { - $config = Token::getTokenStruct(); - $jwtTokenConfig = JwtTokenConfig::createFromArray($config); - - $service = new RefreshTokenService($jwtTokenConfig); - - $token = $service->generate($this->client); - - $isValid = $service->isValid($token->refreshToken); - - $this->assertTrue($isValid); - } - - public function testGenerateValidRefreshTokenFails(): void - { - $config = Token::getTokenStruct(); - $config['algorithmus'] = ''; - $jwtTokenConfig = JwtTokenConfig::createFromArray($config); - - $service = new RefreshTokenService($jwtTokenConfig); - - $this->expectException(DomainException::class); - - $service->generate($this->client); - } -} diff --git a/tests_backup/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php b/tests_backup/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php deleted file mode 100644 index 13d142ae..00000000 --- a/tests_backup/UnitTest/AppTest/Table/AccountAccessAuthTableTest.php +++ /dev/null @@ -1,226 +0,0 @@ -query = new MockQuery(); - $this->hydrator = new AccountAccessAuthHydrator(); - $this->table = new AccountAccessAuthTable($this->query, $this->hydrator); - } - - public function testCanGetTableName(): void - { - $this->assertSame('AccountAccessAuth', $this->table->getTableName()); - } - - public function testCanInsertAccountAccessAuth(): void - { - $accountAccessAuth = $this->hydrator->hydrate(AccountAccessAuth::VALID_DATA); - - $result = $this->table->insert($accountAccessAuth); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testInsertAccountAccessAuthThrowsException(): void - { - $accountAccessAuth = $this->hydrator->hydrate(AccountAccessAuth::VALID_DATA); - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $this->expectException(DuplicateEntryException::class); - - $table->insert($accountAccessAuth); - } - - public function testCanUpdateAccountAccessAuth(): void - { - $accountAccessAuth = $this->hydrator->hydrate(AccountAccessAuth::VALID_DATA); - - $result = $this->table->update($accountAccessAuth); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testUpdateAccountAccessAuthThrowsException(): void - { - $accountAccessAuth = $this->hydrator->hydrate(AccountAccessAuth::VALID_DATA); - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $this->expectException(InvalidArgumentException::class); - - $table->update($accountAccessAuth); - } - - public function testCanDeleteById(): void - { - $result = $this->table->deleteById(AccountAccessAuth::ID); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testDeleteAccountThrowsException(): void - { - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $this->expectException(InvalidArgumentException::class); - - $table->deleteById(AccountAccessAuth::ID); - } - - public function testCanFindById(): void - { - $result = $this->table->findById(AccountAccessAuth::ID); - - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result); - $this->assertSame(AccountAccessAuth::ID, $result->id); - } - - public function testFindByIdIsEmpty(): void - { - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $result = $table->findById(AccountAccessAuth::ID); - - $this->assertNull($result); - } - - public function testCanFindByUserId(): void - { - /** @var AccountAccessAuthCollectionInterface $result */ - $result = $this->table->findByAccountId(AccountAccessAuth::USER_ID); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertSame(AccountAccessAuth::USER_ID, $result[0]->accountId); - } - - public function testFindByUserIdIsEmpty(): void - { - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $result = $table->findByAccountId(AccountAccessAuth::USER_ID); - - $this->assertInstanceOf(AccountAccessAuthCollection::class, $result); - $this->assertEmpty($result); - } - - public function testCanFindByLabel(): void - { - /** @var AccountAccessAuthCollectionInterface $result */ - $result = $this->table->findByLabel(AccountAccessAuth::LABEL); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertSame(AccountAccessAuth::LABEL, $result[0]->label); - } - - public function testFindByLabelIsEmpty(): void - { - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $result = $table->findByLabel(AccountAccessAuth::LABEL); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertEmpty($result); - } - - public function testCanFindByRefreshToken(): void - { - /** @var AccountAccessAuthInterface $result */ - $result = $this->table->findByRefreshToken(AccountAccessAuth::REFRESH_TOKEN); - - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result); - $this->assertSame(AccountAccessAuth::REFRESH_TOKEN, $result->refreshToken); - } - - public function testFindByRefreshTokenIsEmpty(): void - { - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $result = $table->findByRefreshToken(AccountAccessAuth::REFRESH_TOKEN); - - $this->assertNull($result); - } - - public function testCanFindByUserAgent(): void - { - /** @var AccountAccessAuthCollectionInterface $result */ - $result = $this->table->findByUserAgent(AccountAccessAuth::USER_AGENT); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertSame(AccountAccessAuth::USER_AGENT, $result[0]->userAgent); - } - - public function testFindByUserAgentIsEmpty(): void - { - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $result = $table->findByUserAgent(AccountAccessAuth::USER_AGENT); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertEmpty($result); - } - - public function testCanFindByClientIdentHash(): void - { - /** @var AccountAccessAuthInterface $result */ - $result = $this->table->findByClientIdentHash(AccountAccessAuth::CLIENT_IDENT_HASH); - - $this->assertInstanceOf(AccountAccessAuthInterface::class, $result); - $this->assertSame(AccountAccessAuth::CLIENT_IDENT_HASH, $result->clientIdentHash); - } - - public function testFindByClientIdentHashIsEmpty(): void - { - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $result = $table->findByClientIdentHash(AccountAccessAuth::CLIENT_IDENT_HASH); - - $this->assertNull($result); - } - - public function testCanFindAll(): void - { - /** @var AccountAccessAuthCollectionInterface $result */ - $result = $this->table->findAll(); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertArrayHasKey(0, $result); - $this->assertSame(AccountAccessAuth::ID, $result[0]->id); - } - - public function testFindAllIsEmpty(): void - { - $table = new AccountAccessAuthTable(new MockQueryFailed(), $this->hydrator); - - $result = $table->findAll(); - - $this->assertInstanceOf(AccountAccessAuthCollectionInterface::class, $result); - $this->assertEmpty($result); - } -} diff --git a/tests_backup/UnitTest/AppTest/Table/AccountTableTest.php b/tests_backup/UnitTest/AppTest/Table/AccountTableTest.php deleted file mode 100644 index 5a61d62a..00000000 --- a/tests_backup/UnitTest/AppTest/Table/AccountTableTest.php +++ /dev/null @@ -1,189 +0,0 @@ -uuidFactory = new UuidFactory(); - $this->hydrator = new AccountHydrator($this->uuidFactory); - $this->table = new AccountTable($query, $this->hydrator); - } - - public function testCanGetTableName(): void - { - $this->assertSame('Account', $this->table->getTableName()); - } - - public function testCanInsertAccount(): void - { - $account = $this->hydrator->hydrate(Account::VALID_DATA); - - $result = $this->table->insert($account); - - $this->assertIsInt($result); - $this->assertSame(Account::ID, $result); - } - - public function testInsertAccountThrowsException(): void - { - $table = new AccountTable(new MockQueryFailed(), $this->hydrator); - - $account = $this->hydrator->hydrate(Account::VALID_DATA); - - $this->expectException(DuplicateEntryException::class); - - $table->insert($account); - } - - public function testCanUpdateAccount(): void - { - $account = $this->hydrator->hydrate(Account::VALID_DATA); - - $result = $this->table->update($account); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testUpdateAccountThrowsException(): void - { - $table = new AccountTable(new MockQueryFailed(), $this->hydrator); - $account = $this->hydrator->hydrate(Account::VALID_DATA); - - $this->expectException(InvalidArgumentException::class); - - $table->update($account); - } - - public function testCanDeleteById(): void - { - $result = $this->table->deleteById(Account::ID); - - $this->assertIsBool($result); - $this->assertTrue($result); - } - - public function testDeleteAccountThrowsException(): void - { - $table = new AccountTable(new MockQueryFailed(), $this->hydrator); - - $this->expectException(InvalidArgumentException::class); - - $table->deleteById(Account::ID); - } - - /** - * @throws Exception - */ - public function testCanFindById(): void - { - $account = $this->table->findById(Account::ID); - - $this->assertInstanceOf(AccountInterface::class, $account); - $this->assertSame(Account::VALID_DATA, $this->hydrator->extract($account)); - } - - /** - * @throws Exception - */ - public function testFindByIdIsEmpty(): void - { - $result = $this->table->findById(Account::ID_INVALID); - - $this->assertNull($result); - } - - /** - * @throws Exception - */ - public function testCanFindByUuid(): void - { - $uuid = $this->uuidFactory->fromString(Account::UUID); - $account = $this->table->findByUuid($uuid); - - $this->assertInstanceOf(AccountInterface::class, $account); - $this->assertSame(Account::VALID_DATA, $this->hydrator->extract($account)); - } - - /** - * @throws Exception - */ - public function testFindByUuidIsEmpty(): void - { - $uuid = $this->uuidFactory->fromString(Account::UUID_INVALID); - $result = $this->table->findByUuid($uuid); - - $this->assertNull($result); - } - - public function testCanFindByName(): void - { - $account = $this->table->findByName(Account::NAME); - - $this->assertInstanceOf(AccountInterface::class, $account); - $this->assertSame(Account::VALID_DATA, $this->hydrator->extract($account)); - } - - public function testFindByNameIsEmpty(): void - { - $result = $this->table->findByName(Account::NAME_INVALID); - - $this->assertNull($result); - } - - public function testCanFindByEmail(): void - { - $account = $this->table->findByEmail(new EmailType(Account::EMAIL)); - - $this->assertInstanceOf(AccountInterface::class, $account); - $this->assertSame(Account::VALID_DATA, $this->hydrator->extract($account)); - } - - public function testFindByEmailIsEmpty(): void - { - $result = $this->table->findByEmail(new EmailType(Account::EMAIL_INVALID)); - - $this->assertNull($result); - } - - public function testCanFindAllAccount(): void - { - $accounts = $this->table->findAll(); - - $this->assertInstanceOf(AccountCollectionInterface::class, $accounts); - $this->assertSame([0 => Account::VALID_DATA], $this->hydrator->extractCollection($accounts)); - } - - public function testFindAllAccountIsEmpty(): void - { - $table = new AccountTable(new MockQueryFailed(), $this->hydrator); - - $result = $table->findAll(); - - $this->assertInstanceOf(AccountCollectionInterface::class, $result); - $this->assertEmpty($result); - } -} diff --git a/tests_backup/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php b/tests_backup/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php deleted file mode 100644 index b8232a3f..00000000 --- a/tests_backup/UnitTest/CoreTest/Factory/DatabaseFactoryTest.php +++ /dev/null @@ -1,43 +0,0 @@ -expectException(PDOException::class); - - $config = [ - 'database' => [ - 'driver' => 'mysql', - 'user' => 'testUser', - 'password' => 'testPassword', - 'host' => 'https//example.com', - 'port' => 3306, - 'dbname' => 'example_db', - 'error' => PDO::ERRMODE_EXCEPTION, - 'emulate_prepares' => false, - ], - ]; - - $container = new MockContainer(); - $container->add('config', $config); - - $pdo = (new DatabaseFactory())($container); - - $this->assertInstanceOf(PDO::class, $pdo); - } -} diff --git a/tests_backup/UnitTest/CoreTest/Factory/QueryFactoryTest.php b/tests_backup/UnitTest/CoreTest/Factory/QueryFactoryTest.php deleted file mode 100644 index a10806d1..00000000 --- a/tests_backup/UnitTest/CoreTest/Factory/QueryFactoryTest.php +++ /dev/null @@ -1,29 +0,0 @@ -add(PDO::class, new MockPDO()); - - $query = (new QueryFactory())($container); - - $this->assertInstanceOf(Query::class, $query); - } -} diff --git a/tests_backup/UnitTest/JsonRequestHelper.php b/tests_backup/UnitTest/JsonRequestHelper.php deleted file mode 100644 index 265a9fc0..00000000 --- a/tests_backup/UnitTest/JsonRequestHelper.php +++ /dev/null @@ -1,15 +0,0 @@ -getBody()->getContents(), true); - } -} diff --git a/tests_backup/UnitTest/Mock/Constants/Account.php b/tests_backup/UnitTest/Mock/Constants/Account.php deleted file mode 100644 index b1e8cadd..00000000 --- a/tests_backup/UnitTest/Mock/Constants/Account.php +++ /dev/null @@ -1,60 +0,0 @@ - self::ID, - 'uuid' => self::UUID, - 'name' => self::NAME, - 'password' => self::PASSWORD, - 'email' => self::EMAIL, - 'registeredAt' => self::REGISTERED, - 'lastActionAt' => self::LAST_ACTION, - ]; - - public const array INVALID_DATA - = [ - 'id' => self::ID_INVALID, - 'uuid' => self::UUID_INVALID, - 'name' => self::NAME_INVALID, - 'password' => self::PASSWORD_INVALID, - 'email' => self::EMAIL_INVALID, - 'registeredAt' => self::REGISTERED, - 'lastActionAt' => self::LAST_ACTION, - ]; -} diff --git a/tests_backup/UnitTest/Mock/Constants/AccountAccessAuth.php b/tests_backup/UnitTest/Mock/Constants/AccountAccessAuth.php deleted file mode 100644 index 5bfa113b..00000000 --- a/tests_backup/UnitTest/Mock/Constants/AccountAccessAuth.php +++ /dev/null @@ -1,54 +0,0 @@ - self::ID, - 'accountId' => self::USER_ID, - 'label' => self::LABEL, - 'refreshToken' => self::REFRESH_TOKEN, - 'userAgent' => self::USER_AGENT, - 'clientIdentHash' => self::CLIENT_IDENT_HASH, - 'createdAt' => self::CREATED_AT, - ]; - - public const array INVALID_DATA - = [ - 'id' => self::ID_INVALID, - 'accountId' => self::USER_ID_INVALID, - 'label' => self::LABEL_INVALID, - 'refreshToken' => self::REFRESH_TOKEN_INVALID, - 'userAgent' => self::USER_AGENT_INVALID, - 'clientIdentHash' => self::CLIENT_IDENT_HASH_INVALID, - 'createdAt' => self::CREATED_AT, - ]; -} diff --git a/tests_backup/UnitTest/Mock/Constants/Token.php b/tests_backup/UnitTest/Mock/Constants/Token.php deleted file mode 100644 index 3924a447..00000000 --- a/tests_backup/UnitTest/Mock/Constants/Token.php +++ /dev/null @@ -1,21 +0,0 @@ - 'token secret', - 'algorithmus' => 'HS512', - 'duration' => 60 * 60 * 24 * 7 * 12, - 'iss' => 'Issuer of the token', - 'aud' => 'recipients of the token', - ]; - } -} diff --git a/tests_backup/UnitTest/Mock/Database/MockDelete.php b/tests_backup/UnitTest/Mock/Database/MockDelete.php deleted file mode 100644 index e8c9188e..00000000 --- a/tests_backup/UnitTest/Mock/Database/MockDelete.php +++ /dev/null @@ -1,27 +0,0 @@ -handle($this->statements['DELETE FROM'], $this->statements['WHERE'], $this->parameters['WHERE']); - } - - private function handle(string $table, array $where, array $value): bool - { - return match ($table) { - 'Account', 'AccountAccessAuth' => true, - default => false, - }; - } -} diff --git a/tests_backup/UnitTest/Mock/Database/MockDeleteFailed.php b/tests_backup/UnitTest/Mock/Database/MockDeleteFailed.php deleted file mode 100644 index e72df7a3..00000000 --- a/tests_backup/UnitTest/Mock/Database/MockDeleteFailed.php +++ /dev/null @@ -1,24 +0,0 @@ -handle($this->statements['DELETE FROM'], $this->statements['WHERE'], $this->parameters['WHERE']); - } - - private function handle(string $table, array $where, array $value): bool - { - return false; - } -} diff --git a/tests_backup/UnitTest/Mock/Database/MockInsert.php b/tests_backup/UnitTest/Mock/Database/MockInsert.php deleted file mode 100644 index c3e9b2ae..00000000 --- a/tests_backup/UnitTest/Mock/Database/MockInsert.php +++ /dev/null @@ -1,27 +0,0 @@ -handle($this->statements['INSERT INTO'], $this->statements['VALUES']); - } - - private function handle(string $table, array $values): bool - { - return match($table) { - 'Account', 'AccountAccessAuth' => true, - default => false, - }; - } -} diff --git a/tests_backup/UnitTest/Mock/Database/MockInsertFailed.php b/tests_backup/UnitTest/Mock/Database/MockInsertFailed.php deleted file mode 100644 index f64f2fea..00000000 --- a/tests_backup/UnitTest/Mock/Database/MockInsertFailed.php +++ /dev/null @@ -1,25 +0,0 @@ -handle($this->statements['INSERT INTO'], $this->statements['VALUES']); - } - - private function handle(string $table, array $values): bool - { - throw new PDOException(); - } -} diff --git a/tests_backup/UnitTest/Mock/Database/MockPDO.php b/tests_backup/UnitTest/Mock/Database/MockPDO.php deleted file mode 100644 index 51c8ad13..00000000 --- a/tests_backup/UnitTest/Mock/Database/MockPDO.php +++ /dev/null @@ -1,18 +0,0 @@ -statements)) { - return $this->handle($this->statements['FROM'], $this->statements['WHERE'], $this->parameters['WHERE']); - } - - return []; - } - - public function fetchAll($index = '', $selectOnly = ''): false|array - { - return match ($this->getFromTable()) { - 'Account' => [0 => Account::VALID_DATA], - 'AccountAccessAuth' => [0 => AccountAccessAuth::VALID_DATA], - default => false - }; - } - - private function handle(string $from, array $where, array $params): false|array - { - return match ($from) { - 'Account' => $this->handleAccount($where, $params), - 'AccountAccessAuth' => $this->handleAccountAccessAuth($where, $params), - default => false - }; - } - - private function handleAccount(array $where, array $params): false|array - { - if ($where[0][1] === 'id = ?' && $params[0] === Account::ID) { - return Account::VALID_DATA; - } - - if ($where[0][1] === 'uuid = ?' && $params[0] === Account::UUID) { - return Account::VALID_DATA; - } - - if ($where[0][1] === 'name = ?' && $params[0] === Account::NAME) { - return Account::VALID_DATA; - } - - if ($where[0][1] === 'email = ?' && $params[0] === Account::EMAIL) { - return Account::VALID_DATA; - } - - return false; - } - - private function handleAccountAccessAuth(array $where, array $params): false|array - { - if ($where[0][1] === 'id = ?' && $params[0] === AccountAccessAuth::ID) { - return AccountAccessAuth::VALID_DATA; - } - - if ($where[0][1] === 'userId = ?' && $params[0] === AccountAccessAuth::USER_ID) { - return [0 => AccountAccessAuth::VALID_DATA]; - } - - if ($where[0][1] === 'label = ?' && $params[0] === AccountAccessAuth::LABEL) { - return [0 => AccountAccessAuth::VALID_DATA]; - } - - if ($where[0][1] === 'refreshToken = ?' && $params[0] === AccountAccessAuth::REFRESH_TOKEN) { - return AccountAccessAuth::VALID_DATA; - } - - if ($where[0][1] === 'userAgent = ?' && $params[0] === AccountAccessAuth::USER_AGENT) { - return [0 => AccountAccessAuth::VALID_DATA]; - } - - if ($where[0][1] === 'clientIdentHash = ?' && $params[0] === AccountAccessAuth::CLIENT_IDENT_HASH) { - return AccountAccessAuth::VALID_DATA; - } - - return false; - } -} diff --git a/tests_backup/UnitTest/Mock/Database/MockSelectFailed.php b/tests_backup/UnitTest/Mock/Database/MockSelectFailed.php deleted file mode 100644 index 860c6e17..00000000 --- a/tests_backup/UnitTest/Mock/Database/MockSelectFailed.php +++ /dev/null @@ -1,36 +0,0 @@ -statements)) { - return $this->handle($this->statements['FROM'], $this->statements['WHERE'], $this->parameters['WHERE']); - } - - return []; - } - - public function fetchAll($index = '', $selectOnly = ''): false|array - { - return false; - } - - private function handle(string $from, array $where, array $params): false|array - { - return false; - } -} diff --git a/tests_backup/UnitTest/Mock/Database/MockUpdate.php b/tests_backup/UnitTest/Mock/Database/MockUpdate.php deleted file mode 100644 index 0f13c7ef..00000000 --- a/tests_backup/UnitTest/Mock/Database/MockUpdate.php +++ /dev/null @@ -1,22 +0,0 @@ -statements['UPDATE']) { - 'Account', 'AccountAccessAuth' => true, - default => false - }; - } -} diff --git a/tests_backup/UnitTest/Mock/Database/MockUpdateFailed.php b/tests_backup/UnitTest/Mock/Database/MockUpdateFailed.php deleted file mode 100644 index b755be43..00000000 --- a/tests_backup/UnitTest/Mock/Database/MockUpdateFailed.php +++ /dev/null @@ -1,19 +0,0 @@ -getAttribute(AccountInterface::AUTHENTICATED); - $response = new MockResponse(); - - if ($account instanceof AccountInterface) { - return $response->withHeader('Authorization', 'true'); - } - - return $response; - } -} diff --git a/tests_backup/UnitTest/Mock/MockContainer.php b/tests_backup/UnitTest/Mock/MockContainer.php deleted file mode 100644 index 0ed0ee37..00000000 --- a/tests_backup/UnitTest/Mock/MockContainer.php +++ /dev/null @@ -1,32 +0,0 @@ -has($id)) { - return $this->container[$id]; - } - - return null; - } - - public function has(string $id): bool - { - return array_key_exists($id, $this->container); - } - - public function add(string $id, mixed $value): void - { - $this->container[$id] = $value; - } -} diff --git a/tests_backup/UnitTest/Mock/MockRequestHandler.php b/tests_backup/UnitTest/Mock/MockRequestHandler.php deleted file mode 100644 index da40ff9c..00000000 --- a/tests_backup/UnitTest/Mock/MockRequestHandler.php +++ /dev/null @@ -1,15 +0,0 @@ -headers[$name] ?? ''; - } - - public function withHeader($name, $value): MessageInterface - { - $header = clone $this; - $header->headers[$name] = $value; - return $header; - } - - public function getProtocolVersion(): string - { - // TODO: Implement getProtocolVersion() method. - } - - public function withProtocolVersion(string $version): MessageInterface - { - // TODO: Implement withProtocolVersion() method. - } - - public function getHeaders(): array - { - // TODO: Implement getHeaders() method. - } - - public function hasHeader(string $name): bool - { - // TODO: Implement hasHeader() method. - } - - public function getHeader(string $name): array - { - // TODO: Implement getHeader() method. - } - - public function withAddedHeader(string $name, $value): MessageInterface - { - // TODO: Implement withAddedHeader() method. - } - - public function withoutHeader(string $name): MessageInterface - { - // TODO: Implement withoutHeader() method. - } - - public function getBody(): StreamInterface - { - // TODO: Implement getBody() method. - } - - public function withBody(StreamInterface $body): MessageInterface - { - // TODO: Implement withBody() method. - } - - public function getStatusCode(): int - { - // TODO: Implement getStatusCode() method. - } - - public function withStatus(int $code, string $reasonPhrase = ''): ResponseInterface - { - // TODO: Implement withStatus() method. - } - - public function getReasonPhrase(): string - { - // TODO: Implement getReasonPhrase() method. - } -} diff --git a/tests_backup/UnitTest/Mock/MockServerRequest.php b/tests_backup/UnitTest/Mock/MockServerRequest.php deleted file mode 100644 index 0f3c4122..00000000 --- a/tests_backup/UnitTest/Mock/MockServerRequest.php +++ /dev/null @@ -1,192 +0,0 @@ -headers; - } - - public function hasHeader($name): bool - { - return array_key_exists($name, $this->headers); - } - - public function getHeader($name): array - { - return array_key_exists($name, $this->headers) ? $this->headers[$name] : []; - } - - public function getHeaderLine($name): string - { - return $this->headers[$name] ?? ''; - } - - public function withHeader($name, $value): MessageInterface - { - $header = clone $this; - $header->headers[$name] = $value; - - return $header; - } - - /** - * @return StreamInterface|array - */ - public function getBody(): StreamInterface - { - return $this->body; - } - - public function getQueryParams(): array - { - return $this->queryParams; - } - - public function withQueryParams(array $query): self - { - $queryParams = clone $this; - - $queryParams->queryParams = $query; - - return $queryParams; - } - - public function getParsedBody(): object|array|null - { - return $this->body; - } - - public function withParsedBody($data): ServerRequestInterface - { - $body = clone $this; - $body->body = $data; - - return $body; - } - - public function getAttribute($name, $default = null) - { - if (array_key_exists($name, $this->attributes)) { - return $this->attributes[$name]; - } - - return $default; - } - - public function withAttribute($name, $value): MockServerRequest - { - $attributes = clone $this; - $attributes->attributes[$name] = $value; - - return $attributes; - } - - public function getProtocolVersion(): string - { - // TODO: Implement getProtocolVersion() method. - } - - public function withProtocolVersion(string $version): MessageInterface - { - // TODO: Implement withProtocolVersion() method. - } - - public function withAddedHeader(string $name, $value): MessageInterface - { - // TODO: Implement withAddedHeader() method. - } - - public function withoutHeader(string $name): MessageInterface - { - // TODO: Implement withoutHeader() method. - } - - public function withBody(StreamInterface $body): MessageInterface - { - // TODO: Implement withBody() method. - } - - public function getRequestTarget(): string - { - // TODO: Implement getRequestTarget() method. - } - - public function withRequestTarget(string $requestTarget): RequestInterface - { - // TODO: Implement withRequestTarget() method. - } - - public function getMethod(): string - { - // TODO: Implement getMethod() method. - } - - public function withMethod(string $method): RequestInterface - { - // TODO: Implement withMethod() method. - } - - public function getUri(): UriInterface - { - return new \Laminas\Diactoros\Uri('http://example.com/'); - } - - public function withUri(UriInterface $uri, bool $preserveHost = false): RequestInterface - { - // TODO: Implement withUri() method. - } - - public function getServerParams(): array - { - return []; - } - - public function getCookieParams(): array - { - // TODO: Implement getCookieParams() method. - } - - public function withCookieParams(array $cookies): ServerRequestInterface - { - // TODO: Implement withCookieParams() method. - } - - public function getUploadedFiles(): array - { - // TODO: Implement getUploadedFiles() method. - } - - public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface - { - // TODO: Implement withUploadedFiles() method. - } - - public function getAttributes(): array - { - // TODO: Implement getAttributes() method. - } - - public function withoutAttribute(string $name): ServerRequestInterface - { - // TODO: Implement withoutAttribute() method. - } -} diff --git a/tests_backup/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php b/tests_backup/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php deleted file mode 100644 index 78b490c3..00000000 --- a/tests_backup/UnitTest/Mock/Repository/MockAccountAccessAuthRepository.php +++ /dev/null @@ -1,14 +0,0 @@ - $this->config->iss, - 'aud' => $this->config->aud, - 'iat' => $now, - 'exp' => $now + $this->config->duration, - 'uuid' => $uuid->toString(), - ]; - - return AccessToken::fromString(JWT::encode($payload, $this->config->key, $this->config->algorithmus)); - } -} diff --git a/tests_backup/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php b/tests_backup/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php deleted file mode 100644 index aebd77eb..00000000 --- a/tests_backup/UnitTest/Mock/Service/MockAccessTokenServiceWithoutDuration.php +++ /dev/null @@ -1,36 +0,0 @@ - $this->config->iss, - 'aud' => $this->config->aud, - 'iat' => $now, - 'exp' => $now + $this->config->duration, - 'uuid' => $uuid->toString(), - ]; - - return AccessToken::fromString(JWT::encode($payload, $this->config->key, $this->config->algorithmus)); - } -} diff --git a/tests_backup/UnitTest/Mock/Service/MockAuthenticationService.php b/tests_backup/UnitTest/Mock/Service/MockAuthenticationService.php deleted file mode 100644 index 9301076c..00000000 --- a/tests_backup/UnitTest/Mock/Service/MockAuthenticationService.php +++ /dev/null @@ -1,14 +0,0 @@ -accountId !== Account::ID) { - throw new DuplicateEntryException('AccountAccessAuth', $data->id); - } - - return true; - } - - public function update(AccountAccessAuthInterface $data): true - { - if ($data->id !== AccountAccessAuth::ID) { - throw new InvalidArgumentException(); - } - - return true; - } - - public function deleteById(int $id): true - { - if ($id !== AccountAccessAuth::ID) { - throw new InvalidArgumentException(); - } - - return true; - } - - public function findById(int $id): ?AccountAccessAuthInterface - { - return $id === AccountAccessAuth::ID ? $this->hydrator->hydrate(AccountAccessAuth::VALID_DATA) : null; - } - - public function findByAccountId(int $accountId): AccountAccessAuthCollectionInterface - { - return $accountId === AccountAccessAuth::USER_ID - ? $this->hydrator->hydrateCollection([0 => AccountAccessAuth::VALID_DATA]) - : $this->hydrator->hydrateCollection( - [] - ); - } - - public function findByLabel(string $label): AccountAccessAuthCollectionInterface - { - return $label === AccountAccessAuth::LABEL - ? $this->hydrator->hydrateCollection([0 => AccountAccessAuth::VALID_DATA]) - : $this->hydrator->hydrateCollection( - [] - ); - } - - public function findByRefreshToken(string $refreshToken): ?AccountAccessAuthInterface - { - return $refreshToken === AccountAccessAuth::REFRESH_TOKEN ? $this->hydrator->hydrate( - AccountAccessAuth::VALID_DATA - ) : null; - } - - public function findByUserAgent(string $userAgent): AccountAccessAuthCollectionInterface - { - return $userAgent === AccountAccessAuth::USER_AGENT - ? $this->hydrator->hydrateCollection([0 => AccountAccessAuth::VALID_DATA]) - : $this->hydrator->hydrateCollection( - [] - ); - } - - public function findByClientIdentHash(string $clientIdentHash): ?AccountAccessAuthInterface - { - return $clientIdentHash === AccountAccessAuth::CLIENT_IDENT_HASH ? $this->hydrator->hydrate( - AccountAccessAuth::VALID_DATA - ) : null; - } - - public function findAll(): AccountAccessAuthCollectionInterface - { - return $this->hydrator->hydrateCollection([0 => AccountAccessAuth::VALID_DATA]); - } -} diff --git a/tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php b/tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php deleted file mode 100644 index b5019e7c..00000000 --- a/tests_backup/UnitTest/Mock/Table/MockAccountAccessAuthTableFailed.php +++ /dev/null @@ -1,25 +0,0 @@ -hydrator->hydrateCollection([]); - } -} diff --git a/tests_backup/UnitTest/Mock/Table/MockAccountTable.php b/tests_backup/UnitTest/Mock/Table/MockAccountTable.php deleted file mode 100644 index 1fc6fba9..00000000 --- a/tests_backup/UnitTest/Mock/Table/MockAccountTable.php +++ /dev/null @@ -1,84 +0,0 @@ -id !== Account::ID) { - throw new DuplicateEntryException('Account', $data->id); - } - - return 1; - } - - public function update(AccountInterface $data): true - { - if ($data->id !== Account::ID) { - throw new InvalidArgumentException(); - } - - return true; - } - - public function deleteById(int $id): true - { - if ($id !== Account::ID) { - throw new InvalidArgumentException(); - } - - return true; - } - - public function findById(int $id): ?AccountInterface - { - return $id === Account::ID ? $this->hydrator->hydrate(Account::VALID_DATA) : null; - } - - public function findByUuid(UuidInterface $uuid): ?AccountInterface - { - return $uuid->toString() === Account::UUID ? $this->hydrator->hydrate(Account::VALID_DATA) : null; - } - - public function findByName(string $name): ?AccountInterface - { - return $name === Account::NAME ? $this->hydrator->hydrate(Account::VALID_DATA) : null; - } - - public function findByEmail(EmailType $email): ?AccountInterface - { - return $email->toString() === Account::EMAIL ? $this->hydrator->hydrate(Account::VALID_DATA) : null; - } - - public function findAll(): AccountCollection - { - return $this->hydrator->hydrateCollection([Account::VALID_DATA]); - } -} diff --git a/tests_backup/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php b/tests_backup/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php deleted file mode 100644 index f1243729..00000000 --- a/tests_backup/UnitTest/Mock/Table/MockAccountTableAccountAuthenticationMiddlewareInvalidToken.php +++ /dev/null @@ -1,84 +0,0 @@ -id !== Account::ID) { - throw new DuplicateEntryException('Account', $data->id); - } - - return 1; - } - - public function update(AccountInterface $data): true - { - if ($data->id !== Account::ID) { - throw new InvalidArgumentException(); - } - - return true; - } - - public function deleteById(int $id): true - { - if ($id !== Account::ID) { - throw new InvalidArgumentException(); - } - - return true; - } - - public function findById(int $id): ?AccountInterface - { - return $id === Account::ID ? $this->hydrator->hydrate(Account::VALID_DATA) : null; - } - - public function findByUuid(UuidInterface $uuid): ?AccountInterface - { - return null; - } - - public function findByName(string $name): ?AccountInterface - { - return $name === Account::NAME ? $this->hydrator->hydrate(Account::VALID_DATA) : null; - } - - public function findByEmail(EmailType $email): ?AccountInterface - { - return $email->toString() === Account::EMAIL ? $this->hydrator->hydrate(Account::VALID_DATA) : null; - } - - public function findAll(): AccountCollection - { - return $this->hydrator->hydrateCollection([Account::VALID_DATA]); - } -} diff --git a/tests_backup/UnitTest/Mock/Table/MockAccountTableFailed.php b/tests_backup/UnitTest/Mock/Table/MockAccountTableFailed.php deleted file mode 100644 index 13e0f118..00000000 --- a/tests_backup/UnitTest/Mock/Table/MockAccountTableFailed.php +++ /dev/null @@ -1,26 +0,0 @@ -hydrator->hydrateCollection([]); - } -} diff --git a/tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidator.php b/tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidator.php deleted file mode 100644 index 70e86866..00000000 --- a/tests_backup/UnitTest/Mock/Validator/MockAuthenticationValidator.php +++ /dev/null @@ -1,20 +0,0 @@ -