From b48a2a9bf9dadb4636ed41695b29e9096bd172b9 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sat, 5 Oct 2024 15:43:41 -0400 Subject: [PATCH] WIP on Pest test migration --- composer.json | 9 +- composer.lock | 2108 +++++++++++++++++++++++++- phpunit.xml | 18 + src/DocumentException.php | 3 +- tests/Feature/ExampleTest.php | 5 + tests/Pest.php | 53 + tests/TestCase.php | 10 + tests/Unit/ConfigurationTest.php | 36 + tests/Unit/DocumentExceptionTest.php | 40 + tests/Unit/FieldMatchTest.php | 20 + tests/Unit/FieldTest.php | 418 +++++ tests/Unit/ModeTest.php | 23 + tests/Unit/OpTest.php | 47 + tests/Unit/ParametersTest.php | 85 ++ tests/unit/ConfigurationTest.php | 58 - tests/unit/DocumentExceptionTest.php | 56 - tests/unit/FieldMatchTest.php | 32 - tests/unit/FieldTest.php | 683 --------- tests/unit/ModeTest.php | 39 - tests/unit/OpTest.php | 86 -- tests/unit/ParametersTest.php | 134 -- 21 files changed, 2871 insertions(+), 1092 deletions(-) create mode 100644 phpunit.xml create mode 100644 tests/Feature/ExampleTest.php create mode 100644 tests/Pest.php create mode 100644 tests/TestCase.php create mode 100644 tests/Unit/ConfigurationTest.php create mode 100644 tests/Unit/DocumentExceptionTest.php create mode 100644 tests/Unit/FieldMatchTest.php create mode 100644 tests/Unit/FieldTest.php create mode 100644 tests/Unit/ModeTest.php create mode 100644 tests/Unit/OpTest.php create mode 100644 tests/Unit/ParametersTest.php delete mode 100644 tests/unit/ConfigurationTest.php delete mode 100644 tests/unit/DocumentExceptionTest.php delete mode 100644 tests/unit/FieldMatchTest.php delete mode 100644 tests/unit/FieldTest.php delete mode 100644 tests/unit/ModeTest.php delete mode 100644 tests/unit/OpTest.php delete mode 100644 tests/unit/ParametersTest.php diff --git a/composer.json b/composer.json index f25554f..ba24b46 100644 --- a/composer.json +++ b/composer.json @@ -25,9 +25,9 @@ "ext-pdo": "*" }, "require-dev": { - "phpunit/phpunit": "^11", "square/pjson": "^0.5.0", - "phpstan/phpstan": "^1.12" + "phpstan/phpstan": "^1.12", + "pestphp/pest": "^3.2" }, "autoload": { "psr-4": { @@ -47,5 +47,10 @@ }, "archive": { "exclude": [ "/tests", "/.gitattributes", "/.gitignore", "/.git", "/composer.lock" ] + }, + "config": { + "allow-plugins": { + "pestphp/pest-plugin": true + } } } diff --git a/composer.lock b/composer.lock index 75a8b3a..c3c9ee0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ec1fce1531c57de8cb1300e3d1cf2a83", + "content-hash": "a2c56fcb72f4bb062370f85b100f3d31", "packages": [ { "name": "bit-badger/inspired-by-fsharp", @@ -104,6 +104,338 @@ } ], "packages-dev": [ + { + "name": "brianium/paratest", + "version": "v7.5.6", + "source": { + "type": "git", + "url": "https://github.com/paratestphp/paratest.git", + "reference": "8134d62d5b6f98b145f00db1421f39eb1fd0687b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/8134d62d5b6f98b145f00db1421f39eb1fd0687b", + "reference": "8134d62d5b6f98b145f00db1421f39eb1fd0687b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-simplexml": "*", + "fidry/cpu-core-counter": "^1.2.0", + "jean85/pretty-package-versions": "^2.0.6", + "php": "~8.2.0 || ~8.3.0", + "phpunit/php-code-coverage": "^11.0.6", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-timer": "^7.0.1", + "phpunit/phpunit": "^11.3.6", + "sebastian/environment": "^7.2.0", + "symfony/console": "^6.4.11 || ^7.1.4", + "symfony/process": "^6.4.8 || ^7.1.3" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0.0", + "ext-pcov": "*", + "ext-posix": "*", + "infection/infection": "^0.29.6", + "phpstan/phpstan": "^1.12.5", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "squizlabs/php_codesniffer": "^3.10.3", + "symfony/filesystem": "^6.4.9 || ^7.1.2" + }, + "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.5.6" + }, + "funding": [ + { + "url": "https://github.com/sponsors/Slamdunk", + "type": "github" + }, + { + "url": "https://paypal.me/filippotessarotto", + "type": "paypal" + } + ], + "time": "2024-10-02T05:22:28+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "8520451a140d3f46ac33042715115e290cf5785f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "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": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "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.2.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-08-06T10:04:20+00:00" + }, + { + "name": "filp/whoops", + "version": "2.16.0", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.16.0" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2024-09-25T12:00:00+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.0.0", + "php": "^7.1|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^7.5|^8.5|^9.4", + "vimeo/psalm": "^4.3" + }, + "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.0.6" + }, + "time": "2024-03-08T09:58:59+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.12.0", @@ -222,6 +554,514 @@ }, "time": "2024-09-29T13:56:26+00:00" }, + { + "name": "nunomaduro/collision", + "version": "v8.4.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/e7d1aa8ed753f63fa816932bbc89678238843b4a", + "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.15.4", + "nunomaduro/termwind": "^2.0.1", + "php": "^8.2.0", + "symfony/console": "^7.1.3" + }, + "conflict": { + "laravel/framework": "<11.0.0 || >=12.0.0", + "phpunit/phpunit": "<10.5.1 || >=12.0.0" + }, + "require-dev": { + "larastan/larastan": "^2.9.8", + "laravel/framework": "^11.19.0", + "laravel/pint": "^1.17.1", + "laravel/sail": "^1.31.0", + "laravel/sanctum": "^4.0.2", + "laravel/tinker": "^2.9.0", + "orchestra/testbench-core": "^9.2.3", + "pestphp/pest": "^2.35.0 || ^3.0.0", + "sebastian/environment": "^6.1.0 || ^7.0.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", + "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": "2024-08-03T15:32:23+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "e5f21eade88689536c0cdad4c3cd75f3ed26e01a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/e5f21eade88689536c0cdad4c3cd75f3ed26e01a", + "reference": "e5f21eade88689536c0cdad4c3cd75f3ed26e01a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.0.4" + }, + "require-dev": { + "ergebnis/phpstan-rules": "^2.2.0", + "illuminate/console": "^11.1.1", + "laravel/pint": "^1.15.0", + "mockery/mockery": "^1.6.11", + "pestphp/pest": "^2.34.6", + "phpstan/phpstan": "^1.10.66", + "phpstan/phpstan-strict-rules": "^1.5.2", + "symfony/var-dumper": "^7.0.4", + "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.1.0" + }, + "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": "2024-09-05T15:25:50+00:00" + }, + { + "name": "pestphp/pest", + "version": "v3.2.5", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest.git", + "reference": "1e0bb88b734b3b5999a38fa479683c5dc3ee6f2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest/zipball/1e0bb88b734b3b5999a38fa479683c5dc3ee6f2f", + "reference": "1e0bb88b734b3b5999a38fa479683c5dc3ee6f2f", + "shasum": "" + }, + "require": { + "brianium/paratest": "^7.5.5", + "nunomaduro/collision": "^8.4.0", + "nunomaduro/termwind": "^2.1.0", + "pestphp/pest-plugin": "^3.0.0", + "pestphp/pest-plugin-arch": "^3.0.0", + "pestphp/pest-plugin-mutate": "^3.0.5", + "php": "^8.2.0", + "phpunit/phpunit": "^11.3.6" + }, + "conflict": { + "phpunit/phpunit": ">11.3.6", + "sebastian/exporter": "<6.0.0", + "webmozart/assert": "<1.11.0" + }, + "require-dev": { + "pestphp/pest-dev-tools": "^3.0.0", + "pestphp/pest-plugin-type-coverage": "^3.0.1", + "symfony/process": "^7.1.5" + }, + "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.2.5" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2024-10-01T10:55:18+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.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-arch.git", + "reference": "0a27e55a270cfe73d8cb70551b91002ee2cb64b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/0a27e55a270cfe73d8cb70551b91002ee2cb64b0", + "reference": "0a27e55a270cfe73d8cb70551b91002ee2cb64b0", + "shasum": "" + }, + "require": { + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", + "ta-tikoma/phpunit-architecture-test": "^0.8.4" + }, + "require-dev": { + "pestphp/pest": "^3.0.0", + "pestphp/pest-dev-tools": "^3.0.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.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2024-09-08T23:23:55+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", @@ -340,6 +1180,228 @@ }, "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.4.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "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", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" + }, + "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.4.1" + }, + "time": "2024-05-21T05:55:05+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "153ae662783729388a584b4361f2545e4d841e3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" + }, + "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": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + }, + "time": "2024-02-23T11:10:43+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.32.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "6ca22b154efdd9e3c68c56f5d94670920a1c19a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6ca22b154efdd9e3c68c56f5d94670920a1c19a4", + "reference": "6ca22b154efdd9e3c68c56f5d94670920a1c19a4", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "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/1.32.0" + }, + "time": "2024-09-26T07:23:32+00:00" + }, { "name": "phpstan/phpstan", "version": "1.12.5", @@ -821,6 +1883,160 @@ ], "time": "2024-09-19T10:54:28+00:00" }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+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": "sebastian/cli-parser", "version": "3.0.2", @@ -1792,6 +3008,838 @@ }, "time": "2024-03-15T18:19:22+00:00" }, + { + "name": "symfony/console", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/0fa539d12b3ccf068a722bbbffa07ca7079af9ee", + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-20T08:28:38+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.1.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.1.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-08-13T14:28:19+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "5c03ee6369281177f07f7c68252a280beccba847" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/5c03ee6369281177f07f7c68252a280beccba847", + "reference": "5c03ee6369281177f07f7c68252a280beccba847", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-19T21:48:23+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/string", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/d66f9c343fa894ec2037cc928381df90a7ad4306", + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-20T08:28:38+00:00" + }, + { + "name": "ta-tikoma/phpunit-architecture-test", + "version": "0.8.4", + "source": { + "type": "git", + "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", + "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/89f0dea1cb0f0d5744d3ec1764a286af5e006636", + "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18.0 || ^5.0.0", + "php": "^8.1.0", + "phpdocumentor/reflection-docblock": "^5.3.0", + "phpunit/phpunit": "^10.5.5 || ^11.0.0", + "symfony/finder": "^6.4.0 || ^7.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.4" + }, + "time": "2024-01-05T14:10:56+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.3", @@ -1841,6 +3889,64 @@ } ], "time": "2024-03-03T12:36:25+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" } ], "aliases": [], diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..7d0904f --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,18 @@ + + + + + ./tests + + + + + ./app + ./src + + + diff --git a/src/DocumentException.php b/src/DocumentException.php index 5fc5fb9..0d500e2 100644 --- a/src/DocumentException.php +++ b/src/DocumentException.php @@ -9,12 +9,13 @@ declare(strict_types=1); namespace BitBadger\PDODocument; use Exception; +use Stringable; use Throwable; /** * Exceptions occurring during document processing */ -class DocumentException extends Exception +class DocumentException extends Exception implements Stringable { /** * Constructor diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php new file mode 100644 index 0000000..61cd84c --- /dev/null +++ b/tests/Feature/ExampleTest.php @@ -0,0 +1,5 @@ +toBeTrue(); +}); diff --git a/tests/Pest.php b/tests/Pest.php new file mode 100644 index 0000000..5a0e31f --- /dev/null +++ b/tests/Pest.php @@ -0,0 +1,53 @@ +extend(Tests\TestCase::class)->in('Feature'); + +/* +|-------------------------------------------------------------------------- +| 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); +}); + +/* +|-------------------------------------------------------------------------- +| 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. +| +*/ + +/** + * Reset the database mode + */ +function reset_mode(): void +{ + \BitBadger\PDODocument\Configuration::overrideMode(null); +} + +function something() +{ + // .. +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..cfb05b6 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,10 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{AutoId, Configuration, DocumentException}; + +pest()->group('unit'); + +describe('::$idField', function () { + test('has expected default value', function () { + expect(Configuration::$idField)->toBe('id'); + }); +}); + +describe('::$autoId', function () { + test('has expected default value', function () { + expect(Configuration::$autoId)->toBe(AutoId::None); + }); +}); + +describe('::$idStringLength', function () { + test('has expected default value', function () { + expect(Configuration::$idStringLength)->toBe(16); + }); +}); + +describe('::dbConn()', function () { + test('throws if DSN has not been set', function () { + Configuration::useDSN(''); + expect(fn() => Configuration::dbConn())->toThrow(DocumentException::class); + }); +}); diff --git a/tests/Unit/DocumentExceptionTest.php b/tests/Unit/DocumentExceptionTest.php new file mode 100644 index 0000000..21fb6e9 --- /dev/null +++ b/tests/Unit/DocumentExceptionTest.php @@ -0,0 +1,40 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\DocumentException; + +pest()->group('unit'); + +describe('Constructor', function () { + test('fills code and prior exception if provided', function () { + $priorEx = new Exception('Uh oh'); + expect(new DocumentException('Test Exception', 17, $priorEx)) + ->not->toBeNull() + ->getMessage()->toBe('Test Exception') + ->getCode()->toBe(17) + ->getPrevious()->toBe($priorEx); + }); + test('uses expected code and prior exception if not provided', function () { + expect(new DocumentException('Oops')) + ->not->toBeNull() + ->getMessage()->toBe('Oops') + ->getCode()->toBe(0) + ->getPrevious()->toBeNull(); + }); +}); + +describe('->__toString()', function () { + test('excludes code if 0', function () { + $ex = new DocumentException('Test failure'); + expect("$ex")->toBe("BitBadger\PDODocument\DocumentException: Test failure\n"); + }); + test('includes code if non-zero', function () { + $ex = new DocumentException('Oof', -6); + expect("$ex")->toBe("BitBadger\PDODocument\DocumentException: [-6] Oof\n"); + }); +}); diff --git a/tests/Unit/FieldMatchTest.php b/tests/Unit/FieldMatchTest.php new file mode 100644 index 0000000..fee3edb --- /dev/null +++ b/tests/Unit/FieldMatchTest.php @@ -0,0 +1,20 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\FieldMatch; + +pest()->group('unit'); + +describe('->toSQL()', function () { + test('returns AND for All', function () { + expect(FieldMatch::All)->toSQL()->toBe('AND'); + }); + test('returns OR for Any', function () { + expect(FieldMatch::Any)->toSQL()->toBe('OR'); + }); +}); diff --git a/tests/Unit/FieldTest.php b/tests/Unit/FieldTest.php new file mode 100644 index 0000000..cc1cc38 --- /dev/null +++ b/tests/Unit/FieldTest.php @@ -0,0 +1,418 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, Field, Mode, Op}; + +pest()->group('unit'); + +describe('->appendParameter()', function () { + afterEach(function () { Configuration::overrideMode(null); }); + test('appends no parameter for exists', function () { + expect(Field::exists('exists')->appendParameter([]))->toBeEmpty(); + }); + test('appends no parameter for notExists', function () { + expect(Field::notExists('absent')->appendParameter([]))->toBeEmpty(); + }); + test('appends two parameters for between', function () { + expect(Field::between('exists', 5, 9, '@num')->appendParameter([])) + ->toHaveLength(2) + ->toEqual(['@nummin' => 5, '@nummax' => 9]); + }); + test('appends a parameter for each value for in', function () { + expect(Field::in('it', ['test', 'unit', 'great'], ':val')->appendParameter([])) + ->toHaveLength(3) + ->toEqual([':val_0' => 'test', ':val_1' => 'unit', ':val_2' => 'great']); + }); + test('appends a parameter for each value for inArray [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([])) + ->toHaveLength(3) + ->toEqual([':bit_0' => '2', ':bit_1' => '8', ':bit_2' => '64']); + })->group('postgresql'); + test('appends a parameter for each value for inArray [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([])) + ->toHaveLength(3) + ->toEqual([':bit_0' => 2, ':bit_1' => 8, ':bit_2' => 64]); + })->group('sqlite'); + test('appends a parameter for other operators', function () { + expect(Field::equal('the_field', 33, ':test')->appendParameter([])) + ->toHaveLength(1) + ->toEqual([':test' => 33]); + }); +}); + +describe('->path()', function () { + afterEach(function () { Configuration::overrideMode(null); }); + test('returns simple SQL path [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::equal('it', 'that'))->path()->toBe("data->>'it'"); + })->group('postgresql'); + test('returns simple SQL path [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::equal('top', 'that'))->path()->toBe("data->>'top'"); + })->group('sqlite'); + test('returns nested SQL path [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::equal('parts.to.the.path', ''))->path()->toBe("data#>>'{parts,to,the,path}'"); + })->group('postgresql'); + test('returns nested SQL path [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::equal('one.two.three', ''))->path()->toBe("data->'one'->'two'->>'three'"); + })->group('sqlite'); + test('returns simple JSON path [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::equal('it', 'that'))->path(true)->toBe("data->'it'"); + })->group('postgresql'); + test('returns simple JSON path [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::equal('top', 'that'))->path(true)->toBe("data->'top'"); + })->group('sqlite'); + test('returns nested JSON path [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::equal('parts.to.the.path', ''))->path(true)->toBe("data#>'{parts,to,the,path}'"); + })->group('postgresql'); + test('returns nested JSON path [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::equal('one.two.three', ''))->path(true)->toBe("data->'one'->'two'->'three'"); + })->group('sqlite'); +}); + +describe('->toWhere()', function () { + afterEach(function () { Configuration::overrideMode(null); }); + test('generates IS NOT NULL for exists w/o qualifier [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::exists('that_field'))->toWhere()->toBe("data->>'that_field' IS NOT NULL"); + })->group('postgresql'); + test('generates IS NOT NULL for exists w/o qualifier [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::exists('that_field'))->toWhere()->toBe("data->>'that_field' IS NOT NULL"); + })->group('sqlite'); + test('generates IS NULL for notExists w/o qualifier [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::notExists('a_field'))->toWhere()->toBe("data->>'a_field' IS NULL"); + })->group('postgresql'); + test('generates IS NULL for notExists w/o qualifier [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::notExists('a_field'))->toWhere()->toBe("data->>'a_field' IS NULL"); + })->group('sqlite'); + test('generates BETWEEN for between w/o qualifier [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::between('age', 13, 17, '@age'))->toWhere()->toBe("data->>'age' BETWEEN @agemin AND @agemax"); + })->group('sqlite'); + test('generates BETWEEN for between w/o qualifier, numeric range [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::between('age', 13, 17, '@age'))->toWhere() + ->toBe("(data->>'age')::numeric BETWEEN @agemin AND @agemax"); + })->group('postgresql'); + test('generates BETWEEN for between w/o qualifier, non-numeric range [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::between('city', 'Atlanta', 'Chicago', ':city'))->toWhere() + ->toBe("data->>'city' BETWEEN :citymin AND :citymax"); + })->group('postgresql'); + test('generates BETWEEN for between w/ qualifier [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + $field = Field::between('age', 13, 17, '@age'); + $field->qualifier = 'me'; + expect($field)->toWhere()->toBe("me.data->>'age' BETWEEN @agemin AND @agemax"); + })->group('sqlite'); + test('generates BETWEEN for between w/ qualifier, numeric range [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + $field = Field::between('age', 13, 17, '@age'); + $field->qualifier = 'me'; + expect($field)->toWhere()->toBe("(me.data->>'age')::numeric BETWEEN @agemin AND @agemax"); + })->group('postgresql'); + test('generates BETWEEN for between w/ qualifier, non-numeric range [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + $field = Field::between('city', 'Atlanta', 'Chicago', ':city'); + $field->qualifier = 'me'; + expect($field)->toWhere()->toBe("me.data->>'city' BETWEEN :citymin AND :citymax"); + })->group('postgresql'); + test('generates IN for in, non-numeric values [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::in('test', ['Atlanta', 'Chicago'], ':city'))->toWhere() + ->toBe("data->>'test' IN (:city_0, :city_1)"); + })->group('postgresql'); + test('generates IN for in, numeric values [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::in('even', [2, 4, 6], ':nbr'))->toWhere() + ->toBe("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)"); + })->group('postgresql'); + test('generates IN for in [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::in('test', ['Atlanta', 'Chicago'], ':city'))->toWhere() + ->toBe("data->>'test' IN (:city_0, :city_1)"); + })->group('sqlite'); + test('generates clause for inArray [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::inArray('even', 'tbl', [2, 4, 6, 8], ':it'))->toWhere() + ->toBe("data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]"); + })->group('postgresql'); + test('generates clause for inArray [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::inArray('test', 'tbl', ['Atlanta', 'Chicago'], ':city'))->toWhere() + ->toBe("EXISTS (SELECT 1 FROM json_each(tbl.data, '\$.test') WHERE value IN (:city_0, :city_1))"); + })->group('sqlite'); + test('generates clause for other operators w/o qualifier [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Field::equal('some_field', '', ':value'))->toWhere()->toBe("data->>'some_field' = :value"); + })->group('postgresql'); + test('generates clause for other operators w/o qualifier [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Field::equal('some_field', '', ':value'))->toWhere()->toBe("data->>'some_field' = :value"); + })->group('sqlite'); + test('generates no-parameter clause w/ qualifier [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + $field = Field::exists('no_field'); + $field->qualifier = 'test'; + expect($field)->toWhere()->toBe("test.data->>'no_field' IS NOT NULL"); + })->group('postgresql'); + test('generates no-parameter clause w/ qualifier [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + $field = Field::exists('no_field'); + $field->qualifier = 'test'; + expect($field)->toWhere()->toBe("test.data->>'no_field' IS NOT NULL"); + })->group('sqlite'); + test('generates parameter clause w/ qualifier [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + $field = Field::lessOrEqual('le_field', 18, ':it'); + $field->qualifier = 'q'; + expect($field)->toWhere()->toBe("(q.data->>'le_field')::numeric <= :it"); + })->group('postgresql'); + test('generates parameter clause w/ qualifier [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + $field = Field::lessOrEqual('le_field', 18, ':it'); + $field->qualifier = 'q'; + expect($field)->toWhere()->toBe("q.data->>'le_field' <= :it"); + })->group('sqlite'); +}); + +describe('::equal()', function () { + test('creates Field w/o parameter', function () { + $field = Field::equal('my_test', 9); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('my_test') + ->op->toBe(Op::Equal) + ->paramName->toBeEmpty() + ->and($field->value)->toBe(9); + }); + test('creates Field w/ parameter', function () { + $field = Field::equal('another_test', 'turkey', ':test'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('another_test') + ->op->toBe(Op::Equal) + ->paramName->toBe(':test') + ->and($field->value)->toBe('turkey'); + }); +}); + +describe('::greater()', function () { + test('creates Field w/o parameter', function () { + $field = Field::greater('your_test', 4); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('your_test') + ->op->toBe(Op::Greater) + ->paramName->toBeEmpty() + ->and($field->value)->toBe(4); + }); + test('creates Field w/ parameter', function () { + $field = Field::greater('more_test', 'chicken', ':value'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('more_test') + ->op->toBe(Op::Greater) + ->paramName->toBe(':value') + ->and($field->value)->toBe('chicken'); + }); +}); + +describe('::greaterOrEqual()', function () { + test('creates Field w/o parameter', function () { + $field = Field::greaterOrEqual('their_test', 6); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('their_test') + ->op->toBe(Op::GreaterOrEqual) + ->paramName->toBeEmpty() + ->and($field->value)->toBe(6); + }); + test('creates Field w/ parameter', function () { + $field = Field::greaterOrEqual('greater_test', 'poultry', ':cluck'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('greater_test') + ->op->toBe(Op::GreaterOrEqual) + ->paramName->toBe(':cluck') + ->and($field->value)->toBe('poultry'); + }); +}); + +describe('::less()', function () { + test('creates Field w/o parameter', function () { + $field = Field::less('z', 32); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('z') + ->op->toBe(Op::Less) + ->paramName->toBeEmpty() + ->and($field->value)->toBe(32); + }); + test('creates Field w/ parameter', function () { + $field = Field::less('additional_test', 'fowl', ':boo'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('additional_test') + ->op->toBe(Op::Less) + ->paramName->toBe(':boo') + ->and($field->value)->toBe('fowl'); + }); +}); + +describe('::lessOrEqual()', function () { + test('creates Field w/o parameter', function () { + $field = Field::lessOrEqual('g', 87); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('g') + ->op->toBe(Op::LessOrEqual) + ->paramName->toBeEmpty() + ->and($field->value)->toBe(87); + }); + test('creates Field w/ parameter', function () { + $field = Field::lessOrEqual('lesser_test', 'hen', ':woo'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('lesser_test') + ->op->toBe(Op::LessOrEqual) + ->paramName->toBe(':woo') + ->and($field->value)->toBe('hen'); + }); +}); + +describe('::notEqual()', function () { + test('creates Field w/o parameter', function () { + $field = Field::notEqual('j', 65); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('j') + ->op->toBe(Op::NotEqual) + ->paramName->toBeEmpty() + ->and($field->value)->toBe(65); + }); + test('creates Field w/ parameter', function () { + $field = Field::notEqual('unequal_test', 'egg', ':zoo'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('unequal_test') + ->op->toBe(Op::NotEqual) + ->paramName->toBe(':zoo') + ->and($field->value)->toBe('egg'); + }); +}); + +describe('::between()', function () { + test('creates Field w/o parameter', function () { + $field = Field::between('k', 'alpha', 'zed'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('k') + ->op->toBe(Op::Between) + ->paramName->toBeEmpty() + ->and($field->value)->toEqual(['alpha', 'zed']); + }); + test('creates Field w/ parameter', function () { + $field = Field::between('between_test', 18, 49, ':count'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('between_test') + ->op->toBe(Op::Between) + ->paramName->toBe(':count') + ->and($field->value)->toEqual([18, 49]); + }); +}); + +describe('::in()', function () { + test('creates Field w/o parameter', function () { + $field = Field::in('test', [1, 2, 3]); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('test') + ->op->toBe(Op::In) + ->paramName->toBeEmpty() + ->and($field->value)->toEqual([1, 2, 3]); + }); + test('creates Field w/ parameter', function () { + $field = Field::in('unit', ['a', 'b'], ':inParam'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('unit') + ->op->toBe(Op::In) + ->paramName->toBe(':inParam') + ->and($field->value)->toEqual(['a', 'b']); + }); +}); + +describe('::inArray()', function () { + test('creates Field w/o parameter', function () { + $field = Field::inArray('test', 'tbl', [1, 2, 3]); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('test') + ->op->toBe(Op::InArray) + ->paramName->toBeEmpty() + ->and($field->value)->toEqual(['table' => 'tbl', 'values' => [1, 2, 3]]); + }); + test('creates Field w/ parameter', function () { + $field = Field::inArray('unit', 'tab', ['a', 'b'], ':inAParam'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('unit') + ->op->toBe(Op::InArray) + ->paramName->toBe(':inAParam') + ->and($field->value)->toEqual(['table' => 'tab', 'values' => ['a', 'b']]); + }); +}); + +describe('::exists()', function () { + test('creates Field', function () { + $field = Field::exists('be_there'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('be_there') + ->op->toBe(Op::Exists) + ->paramName->toBeEmpty() + ->and($field->value)->toBeEmpty(); + }); +}); + +describe('::notExists()', function () { + test('creates Field', function () { + $field = Field::notExists('be_absent'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('be_absent') + ->op->toBe(Op::NotExists) + ->paramName->toBeEmpty() + ->and($field->value)->toBeEmpty(); + }); +}); + +describe('::named()', function () { + test('creates Field', function () { + $field = Field::named('the_field'); + expect($field) + ->not->toBeNull() + ->fieldName->toBe('the_field') + ->op->toBe(Op::Equal) + ->value->toBeEmpty() + ->and($field->value)->toBeEmpty(); + }); +}); diff --git a/tests/Unit/ModeTest.php b/tests/Unit/ModeTest.php new file mode 100644 index 0000000..e8f569a --- /dev/null +++ b/tests/Unit/ModeTest.php @@ -0,0 +1,23 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{DocumentException, Mode}; + +pest()->group('unit'); + +describe('::deriveFromDSN()', function () { + test('derives for PostgreSQL', function () { + expect(Mode::deriveFromDSN('pgsql:Host=localhost'))->toBe(Mode::PgSQL); + })->group('postgresql'); + test('derives for SQLite', function () { + expect(Mode::deriveFromDSN('sqlite:data.db'))->toBe(Mode::SQLite); + })->group('sqlite'); + test('throws for other drivers', function () { + expect(fn() => Mode::deriveFromDSN('mysql:Host=localhost'))->toThrow(DocumentException::class); + }); +}); diff --git a/tests/Unit/OpTest.php b/tests/Unit/OpTest.php new file mode 100644 index 0000000..8311ef2 --- /dev/null +++ b/tests/Unit/OpTest.php @@ -0,0 +1,47 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\Op; + +pest()->group('unit'); + +describe('->toSQL()', function () { + test('returns "=" for Equal', function () { + expect(Op::Equal)->toSQL()->toBe('='); + }); + test('returns ">" for Greater', function () { + expect(Op::Greater)->toSQL()->toBe('>'); + }); + test('returns ">=" for GreaterOrEqual', function () { + expect(Op::GreaterOrEqual)->toSQL()->toBe('>='); + }); + test('returns "<" for Less', function () { + expect(Op::Less)->toSQL()->toBe('<'); + }); + test('returns "<=" for LessOrEqual', function () { + expect(Op::LessOrEqual)->toSQL()->toBe('<='); + }); + test('returns "<>" for NotEqual', function () { + expect(Op::NotEqual)->toSQL()->toBe('<>'); + }); + test('returns "BETWEEN" for Between', function () { + expect(Op::Between)->toSQL()->toBe('BETWEEN'); + }); + test('returns "IN" for In', function () { + expect(Op::In)->toSQL()->toBe('IN'); + }); + test('returns "?|" (escaped) for InArray', function () { + expect(Op::InArray)->toSQL()->toBe('??|'); + }); + test('returns "IS NOT NULL" for Exists', function () { + expect(Op::Exists)->toSQL()->toBe('IS NOT NULL'); + }); + test('returns "IS NULL" for NotExists', function () { + expect(Op::NotExists)->toSQL()->toBe('IS NULL'); + }); +}); diff --git a/tests/Unit/ParametersTest.php b/tests/Unit/ParametersTest.php new file mode 100644 index 0000000..b40deea --- /dev/null +++ b/tests/Unit/ParametersTest.php @@ -0,0 +1,85 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Parameters}; +use Test\{PjsonDocument, PjsonId}; + +pest()->group('unit'); + +describe('::id()', function () { + test('creates string ID parameter', function () { + expect(Parameters::id('key'))->toEqual([':id' => 'key']); + }); + test('creates string from numeric ID parameter', function () { + expect(Parameters::id(7))->toEqual([':id' => '7']); + }); +}); + +describe('::json()', function () { + test('serializes an array', function () { + expect(Parameters::json(':it', ['id' => 18, 'url' => 'https://www.unittest.com'])) + ->toEqual([':it' => '{"id":18,"url":"https://www.unittest.com"}']); + }); + test('serializes an array w/ an empty array value', function () { + expect(Parameters::json(':it', ['id' => 18, 'urls' => []]))->toEqual([':it' => '{"id":18,"urls":[]}']); + }); + test('serializes a 1-D array w/ an empty array value', function () { + expect(Parameters::json(':it', ['urls' => []]))->toEqual([':it' => '{"urls":[]}']); + }); + test('serializes a stdClass instance', function () { + $obj = new stdClass(); + $obj->id = 19; + $obj->url = 'https://testhere.info'; + expect(Parameters::json(':it', $obj))->toEqual([':it' => '{"id":19,"url":"https://testhere.info"}']); + }); + test('serializes a Pjson class instance', function () { + expect(Parameters::json(':it', new PjsonDocument(new PjsonId('999'), 'a test', 98, 'nothing'))) + ->toEqual([':it' => '{"id":"999","name":"a test","num_value":98}']); + }); + test('serializes an array of Pjson class instances', function () { + expect(Parameters::json(':it', + ['pjson' => [new PjsonDocument(new PjsonId('997'), 'another test', 94, 'nothing')]])) + ->toEqual([':it' => '{"pjson":[{"id":"997","name":"another test","num_value":94}]}']); + }); +}); + +describe('::nameFields()', function () { + test('provides missing parameter names', function () { + $named = [Field::equal('it', 17), Field::equal('also', 22, ':also'), Field::equal('other', 24)]; + Parameters::nameFields($named); + expect($named) + ->toHaveLength(3) + ->sequence( + fn($it) => $it->paramName->toBe(':field0'), + fn($it) => $it->paramName->toBe(':also'), + fn($it) => $it->paramName->toBe(':field2')); + }); +}); + +describe('::addFields()', function () { + test('appends to an existing parameter array', function () { + expect(Parameters::addFields([Field::equal('b', 'two', ':b'), Field::equal('z', 18, ':z')], [':a' => 1])) + ->toEqual([':a' => 1, ':b' => 'two', ':z' => 18]); + }); +}); + +describe('::fieldNames()', function () { + afterEach(function () { Configuration::overrideMode(null); }); + test('generates names [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Parameters::fieldNames(':names', ['one', 'two', 'seven']))->toEqual([':names' => "{one,two,seven}"]); + })->group('postgresql'); + test('generates names [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Parameters::fieldNames(':it', ['test', 'unit', 'wow'])) + ->toEqual([':it0' => '$.test', ':it1' => '$.unit', ':it2' => '$.wow']); + })->group('sqlite'); + test('throws when mode is not set', function () { + expect(fn() => Parameters::fieldNames('', []))->toThrow(DocumentException::class); + }); +}); diff --git a/tests/unit/ConfigurationTest.php b/tests/unit/ConfigurationTest.php deleted file mode 100644 index acbffe1..0000000 --- a/tests/unit/ConfigurationTest.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit; - -use BitBadger\PDODocument\{AutoId, Configuration, DocumentException}; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Configuration class - */ -#[TestDox('Configuration (Unit tests)')] -class ConfigurationTest extends TestCase -{ - #[TestDox('id default succeeds')] - public function testIdFieldDefaultSucceeds(): void - { - $this->assertEquals('id', Configuration::$idField, 'Default ID field should be "id"'); - } - - #[TestDox('id change succeeds')] - public function testIdFieldChangeSucceeds(): void - { - try { - Configuration::$idField = 'EyeDee'; - $this->assertEquals('EyeDee', Configuration::$idField, 'ID field should have been updated'); - } finally { - Configuration::$idField = 'id'; - $this->assertEquals('id', Configuration::$idField, 'Default ID value should have been restored'); - } - } - - #[TestDox('autoId default succeeds')] - public function testAutoIdDefaultSucceeds(): void - { - $this->assertEquals(AutoId::None, Configuration::$autoId, 'Auto ID should default to None'); - } - - #[TestDox('idStringLength default succeeds')] - public function testIdStringLengthDefaultSucceeds(): void - { - $this->assertEquals(16, Configuration::$idStringLength, 'ID string length should default to 16'); - } - - #[TestDox("dbConn() fails when no DSN specified")] - public function testDbConnFailsWhenNoDSNSpecified(): void - { - $this->expectException(DocumentException::class); - Configuration::useDSN(''); - Configuration::dbConn(); - } -} diff --git a/tests/unit/DocumentExceptionTest.php b/tests/unit/DocumentExceptionTest.php deleted file mode 100644 index c656055..0000000 --- a/tests/unit/DocumentExceptionTest.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit; - -use BitBadger\PDODocument\DocumentException; -use Exception; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the DocumentException class - */ -#[TestDox('Document Exception (Unit tests)')] -class DocumentExceptionTest extends TestCase -{ - public function testConstructorSucceedsWithCodeAndPriorException(): void - { - $priorEx = new Exception('Uh oh'); - $ex = new DocumentException('Test Exception', 17, $priorEx); - $this->assertNotNull($ex, 'The exception should not have been null'); - $this->assertEquals('Test Exception', $ex->getMessage(), 'Message not filled properly'); - $this->assertEquals(17, $ex->getCode(), 'Code not filled properly'); - $this->assertSame($priorEx, $ex->getPrevious(), 'Prior exception not filled properly'); - } - - public function testConstructorSucceedsWithoutCodeAndPriorException(): void - { - $ex = new DocumentException('Oops'); - $this->assertNotNull($ex, 'The exception should not have been null'); - $this->assertEquals('Oops', $ex->getMessage(), 'Message not filled properly'); - $this->assertEquals(0, $ex->getCode(), 'Code not filled properly'); - $this->assertNull($ex->getPrevious(), 'Prior exception should have been null'); - } - - #[TestDox('toString() succeeds without code')] - public function testToStringSucceedsWithoutCode(): void - { - $ex = new DocumentException('Test failure'); - $this->assertEquals("BitBadger\PDODocument\DocumentException: Test failure\n", "$ex", - 'toString not generated correctly'); - } - - #[TestDox('toString() succeeds with code')] - public function testToStringSucceedsWithCode(): void - { - $ex = new DocumentException('Oof', -6); - $this->assertEquals("BitBadger\PDODocument\DocumentException: [-6] Oof\n", "$ex", - 'toString not generated correctly'); - } -} diff --git a/tests/unit/FieldMatchTest.php b/tests/unit/FieldMatchTest.php deleted file mode 100644 index f1d0193..0000000 --- a/tests/unit/FieldMatchTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit; - -use BitBadger\PDODocument\FieldMatch; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the FieldMatch enum - */ -#[TestDox('Field Match (Unit tests)')] -class FieldMatchTest extends TestCase -{ - #[TestDox('toSQL() succeeds for All')] - public function testToSQLSucceedsForAll(): void - { - $this->assertEquals('AND', FieldMatch::All->toSQL(), 'All should have returned AND'); - } - - #[TestDox('toSQL() succeeds for Any')] - public function testToSQLSucceedsForAny(): void - { - $this->assertEquals('OR', FieldMatch::Any->toSQL(), 'Any should have returned OR'); - } -} diff --git a/tests/unit/FieldTest.php b/tests/unit/FieldTest.php deleted file mode 100644 index 4bf06ec..0000000 --- a/tests/unit/FieldTest.php +++ /dev/null @@ -1,683 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit; - -use BitBadger\PDODocument\{Configuration, Field, Mode, Op}; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Field class - */ -#[TestDox('Field (Unit tests)')] -class FieldTest extends TestCase -{ - #[TestDox('appendParameter() succeeds for exists')] - public function testAppendParameterSucceedsForExists(): void - { - $this->assertEquals([], Field::exists('exists')->appendParameter([]), - 'exists should not have appended a parameter'); - } - - #[TestDox('appendParameter() succeeds for notExists')] - public function testAppendParameterSucceedsForNotExists(): void - { - $this->assertEquals([], Field::notExists('absent')->appendParameter([]), - 'notExists should not have appended a parameter'); - } - - #[TestDox('appendParameter() succeeds for between')] - public function testAppendParameterSucceedsForBetween(): void - { - $this->assertEquals(['@nummin' => 5, '@nummax' => 9], - Field::between('exists', 5, 9, '@num')->appendParameter([]), - 'Between should have appended min and max parameters'); - } - - #[TestDox('appendParameter() succeeds for in')] - public function testAppendParameterSucceedsForIn(): void - { - $this->assertEquals([':val_0' => 'test', ':val_1' => 'unit', ':val_2' => 'great'], - Field::in('it', ['test', 'unit', 'great'], ':val')->appendParameter([]), - 'In should have appended 3 parameters for the input values'); - } - - #[TestDox('appendParameter() succeeds for inArray for PostgreSQL')] - public function testAppendParameterSucceedsForInArrayForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals([':bit_0' => '2', ':bit_1' => '8', ':bit_2' => '64'], - Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([]), - 'InArray should have appended 3 string parameters for the input values'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('appendParameter() succeeds for inArray for SQLite')] - public function testAppendParameterSucceedsForInArrayForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals([':bit_0' => 2, ':bit_1' => 8, ':bit_2' => 64], - Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([]), - 'InArray should have appended 3 parameters for the input values'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('appendParameter() succeeds for others')] - public function testAppendParameterSucceedsForOthers(): void - { - $this->assertEquals(['@test' => 33], Field::equal('the_field', 33, '@test')->appendParameter([]), - 'Field parameter not returned correctly'); - } - - #[TestDox('path() succeeds for simple SQL path for PostgreSQL')] - public function testPathSucceedsForSimpleSqlPathForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("data->>'it'", Field::equal('it', 'that')->path(), - 'SQL value path not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('path() succeeds for simple SQL path for SQLite')] - public function testPathSucceedsForSimpleSqlPathForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals("data->>'top'", Field::equal('top', 'that')->path(), - 'SQL value path not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('path() succeeds for nested SQL path for PostgreSQL')] - public function testPathSucceedsForNestedSqlPathForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("data#>>'{parts,to,the,path}'", Field::equal('parts.to.the.path', '')->path(), - 'SQL value path not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('path() succeeds for nested SQL path for SQLite')] - public function testPathSucceedsForNestedSqlPathForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals("data->'one'->'two'->>'three'", Field::equal('one.two.three', '')->path(), - 'SQL value path not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('path() succeeds for simple JSON path for PostgreSQL')] - public function testPathSucceedsForSimpleJsonPathForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("data->'it'", Field::equal('it', 'that')->path(true), - 'JSON value path not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('path() succeeds for simple JSON path for SQLite')] - public function testPathSucceedsForSimpleJsonPathForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals("data->'top'", Field::equal('top', 'that')->path(true), - 'JSON value path not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('path() succeeds for nested JSON path for PostgreSQL')] - public function testPathSucceedsForNestedJsonPathForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("data#>'{parts,to,the,path}'", Field::equal('parts.to.the.path', '')->path(true), - 'JSON value path not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('path() succeeds for nested JSON path for SQLite')] - public function testPathSucceedsForNestedJsonPathForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals("data->'one'->'two'->'three'", Field::equal('one.two.three', '')->path(true), - 'SQL value path not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for exists without qualifier for PostgreSQL')] - public function testToWhereSucceedsForExistsWithoutQualifierForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("data->>'that_field' IS NOT NULL", Field::exists('that_field')->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for exists without qualifier for SQLite')] - public function testToWhereSucceedsForExistsWithoutQualifierForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals("data->>'that_field' IS NOT NULL", Field::exists('that_field')->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for notExists without qualifier for PostgreSQL')] - public function testToWhereSucceedsForNotExistsWithoutQualifierForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("data->>'a_field' IS NULL", Field::notExists('a_field')->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for notExists without qualifier for SQLite')] - public function testToWhereSucceedsForNotExistsWithoutQualifierForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals("data->>'a_field' IS NULL", Field::notExists('a_field')->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for between without qualifier for SQLite')] - public function testToWhereSucceedsForBetweenWithoutQualifierForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals("data->>'age' BETWEEN @agemin AND @agemax", - Field::between('age', 13, 17, '@age')->toWhere(), 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for between without qualifier for PostgreSQL with numeric range')] - public function testToWhereSucceedsForBetweenWithoutQualifierForPostgreSQLWithNumericRange(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("(data->>'age')::numeric BETWEEN @agemin AND @agemax", - Field::between('age', 13, 17, '@age')->toWhere(), 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for between without qualifier for PostgreSQL with non-numeric range')] - public function testToWhereSucceedsForBetweenWithoutQualifierForPostgreSQLWithNonNumericRange(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("data->>'city' BETWEEN :citymin AND :citymax", - Field::between('city', 'Atlanta', 'Chicago', ':city')->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for between with qualifier for SQLite')] - public function testToWhereSucceedsForBetweenWithQualifierForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $field = Field::between('age', 13, 17, '@age'); - $field->qualifier = 'me'; - $this->assertEquals("me.data->>'age' BETWEEN @agemin AND @agemax", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for between with qualifier for PostgreSQL with numeric range')] - public function testToWhereSucceedsForBetweenWithQualifierForPostgreSQLWithNumericRange(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $field = Field::between('age', 13, 17, '@age'); - $field->qualifier = 'me'; - $this->assertEquals("(me.data->>'age')::numeric BETWEEN @agemin AND @agemax", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for between with qualifier for PostgreSQL with non-numeric range')] - public function testToWhereSucceedsForBetweenWithQualifierForPostgreSQLWithNonNumericRange(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $field = Field::between('city', 'Atlanta', 'Chicago', ':city'); - $field->qualifier = 'me'; - $this->assertEquals("me.data->>'city' BETWEEN :citymin AND :citymax", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for in for PostgreSQL with non-numeric values')] - public function testToWhereSucceedsForInForPostgreSQLWithNonNumericValues(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $field = Field::in('test', ['Atlanta', 'Chicago'], ':city'); - $this->assertEquals("data->>'test' IN (:city_0, :city_1)", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for in for PostgreSQL with numeric values')] - public function testToWhereSucceedsForInForPostgreSQLWithNumericValues(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $field = Field::in('even', [2, 4, 6], ':nbr'); - $this->assertEquals("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for in for SQLite')] - public function testToWhereSucceedsForInForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $field = Field::in('test', ['Atlanta', 'Chicago'], ':city'); - $this->assertEquals("data->>'test' IN (:city_0, :city_1)", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for inArray for PostgreSQL')] - public function testToWhereSucceedsForInArrayForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $field = Field::inArray('even', 'tbl', [2, 4, 6, 8], ':it'); - $this->assertEquals("data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for inArray for SQLite')] - public function testToWhereSucceedsForInArrayForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $field = Field::inArray('test', 'tbl', ['Atlanta', 'Chicago'], ':city'); - $this->assertEquals( - "EXISTS (SELECT 1 FROM json_each(tbl.data, '\$.test') WHERE value IN (:city_0, :city_1))", - $field->toWhere(), 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for others without qualifier for PostgreSQL')] - public function testToWhereSucceedsForOthersWithoutQualifierForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $this->assertEquals("data->>'some_field' = @value", Field::equal('some_field', '', '@value')->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds for others without qualifier for SQLite')] - public function testToWhereSucceedsForOthersWithoutQualifierForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $this->assertEquals("data->>'some_field' = @value", Field::equal('some_field', '', '@value')->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds with qualifier no parameter for PostgreSQL')] - public function testToWhereSucceedsWithQualifierNoParameterForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $field = Field::exists('no_field'); - $field->qualifier = 'test'; - $this->assertEquals("test.data->>'no_field' IS NOT NULL", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds with qualifier no parameter for SQLite')] - public function testToWhereSucceedsWithQualifierNoParameterForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $field = Field::exists('no_field'); - $field->qualifier = 'test'; - $this->assertEquals("test.data->>'no_field' IS NOT NULL", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds with qualifier and parameter for PostgreSQL')] - public function testToWhereSucceedsWithQualifierAndParameterForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - try { - $field = Field::lessOrEqual('le_field', 18, '@it'); - $field->qualifier = 'q'; - $this->assertEquals("(q.data->>'le_field')::numeric <= @it", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('toWhere() succeeds with qualifier and parameter for SQLite')] - public function testToWhereSucceedsWithQualifierAndParameterForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - try { - $field = Field::lessOrEqual('le_field', 18, '@it'); - $field->qualifier = 'q'; - $this->assertEquals("q.data->>'le_field' <= @it", $field->toWhere(), - 'WHERE fragment not generated correctly'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('equal() succeeds without parameter')] - public function testEqualSucceedsWithoutParameter(): void - { - $field = Field::equal('my_test', 9); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('my_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Equal, $field->op, 'Operation not filled correctly'); - $this->assertEquals(9, $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('equal() succeeds with parameter')] - public function testEqualSucceedsWithParameter(): void - { - $field = Field::equal('another_test', 'turkey', '@test'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('another_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Equal, $field->op, 'Operation not filled correctly'); - $this->assertEquals('turkey', $field->value, 'Value not filled correctly'); - $this->assertEquals('@test', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('greater() succeeds without parameter')] - public function testGreaterSucceedsWithoutParameter(): void - { - $field = Field::greater('your_test', 4); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('your_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Greater, $field->op, 'Operation not filled correctly'); - $this->assertEquals(4, $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('greater() succeeds with parameter')] - public function testGreaterSucceedsWithParameter(): void - { - $field = Field::greater('more_test', 'chicken', '@value'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('more_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Greater, $field->op, 'Operation not filled correctly'); - $this->assertEquals('chicken', $field->value, 'Value not filled correctly'); - $this->assertEquals('@value', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('greaterOrEqual() succeeds without parameter')] - public function testGreaterOrEqualSucceedsWithoutParameter(): void - { - $field = Field::greaterOrEqual('their_test', 6); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('their_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::GreaterOrEqual, $field->op, 'Operation not filled correctly'); - $this->assertEquals(6, $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('greaterOrEqual() succeeds with parameter')] - public function testGreaterOrEqualSucceedsWithParameter(): void - { - $field = Field::greaterOrEqual('greater_test', 'poultry', '@cluck'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('greater_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::GreaterOrEqual, $field->op, 'Operation not filled correctly'); - $this->assertEquals('poultry', $field->value, 'Value not filled correctly'); - $this->assertEquals('@cluck', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('less() succeeds without parameter')] - public function testLessSucceedsWithoutParameter(): void - { - $field = Field::less('z', 32); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('z', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Less, $field->op, 'Operation not filled correctly'); - $this->assertEquals(32, $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('less() succeeds with parameter')] - public function testLessSucceedsWithParameter(): void - { - $field = Field::less('additional_test', 'fowl', '@boo'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('additional_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Less, $field->op, 'Operation not filled correctly'); - $this->assertEquals('fowl', $field->value, 'Value not filled correctly'); - $this->assertEquals('@boo', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('lessOrEqual() succeeds without parameter')] - public function testLessOrEqualSucceedsWithoutParameter(): void - { - $field = Field::lessOrEqual('g', 87); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('g', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::LessOrEqual, $field->op, 'Operation not filled correctly'); - $this->assertEquals(87, $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('lessOrEqual() succeeds with parameter')] - public function testLessOrEqualSucceedsWithParameter(): void - { - $field = Field::lessOrEqual('lesser_test', 'hen', '@woo'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('lesser_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::LessOrEqual, $field->op, 'Operation not filled correctly'); - $this->assertEquals('hen', $field->value, 'Value not filled correctly'); - $this->assertEquals('@woo', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('notEqual() succeeds without parameter')] - public function testNotEqualSucceedsWithoutParameter(): void - { - $field = Field::notEqual('j', 65); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('j', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::NotEqual, $field->op, 'Operation not filled correctly'); - $this->assertEquals(65, $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('notEqual() succeeds with parameter')] - public function testNotEqualSucceedsWithParameter(): void - { - $field = Field::notEqual('unequal_test', 'egg', '@zoo'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('unequal_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::NotEqual, $field->op, 'Operation not filled correctly'); - $this->assertEquals('egg', $field->value, 'Value not filled correctly'); - $this->assertEquals('@zoo', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('between() succeeds without parameter')] - public function testBetweenSucceedsWithoutParameter(): void - { - $field = Field::between('k', 'alpha', 'zed'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('k', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Between, $field->op, 'Operation not filled correctly'); - $this->assertEquals(['alpha', 'zed'], $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('between() succeeds with parameter')] - public function testBetweenSucceedsWithParameter(): void - { - $field = Field::between('between_test', 18, 49, '@count'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('between_test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Between, $field->op, 'Operation not filled correctly'); - $this->assertEquals([18, 49], $field->value, 'Value not filled correctly'); - $this->assertEquals('@count', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('in() succeeds without parameter')] - public function testInSucceedsWithoutParameter(): void - { - $field = Field::in('test', [1, 2, 3]); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::In, $field->op, 'Operation not filled correctly'); - $this->assertEquals([1, 2, 3], $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('in() succeeds with parameter')] - public function testInSucceedsWithParameter(): void - { - $field = Field::in('unit', ['a', 'b'], '@inParam'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('unit', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::In, $field->op, 'Operation not filled correctly'); - $this->assertEquals(['a', 'b'], $field->value, 'Value not filled correctly'); - $this->assertEquals('@inParam', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('inArray() succeeds without parameter')] - public function testInArraySucceedsWithoutParameter(): void - { - $field = Field::inArray('test', 'tbl', [1, 2, 3]); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('test', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::InArray, $field->op, 'Operation not filled correctly'); - $this->assertEquals(['table' => 'tbl', 'values' => [1, 2, 3]], $field->value, 'Value not filled correctly'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('inArray() succeeds with parameter')] - public function testInArraySucceedsWithParameter(): void - { - $field = Field::inArray('unit', 'tab', ['a', 'b'], '@inAParam'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('unit', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::InArray, $field->op, 'Operation not filled correctly'); - $this->assertEquals(['table' => 'tab', 'values' => ['a', 'b']], $field->value, 'Value not filled correctly'); - $this->assertEquals('@inAParam', $field->paramName, 'Parameter name not filled correctly'); - } - - #[TestDox('exists() succeeds')] - public function testExistsSucceeds(): void - { - $field = Field::exists('be_there'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('be_there', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Exists, $field->op, 'Operation not filled correctly'); - $this->assertEquals('', $field->value, 'Value should have been blank'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('notExists() succeeds')] - public function testNotExistsSucceeds(): void - { - $field = Field::notExists('be_absent'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('be_absent', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::NotExists, $field->op, 'Operation not filled correctly'); - $this->assertEquals('', $field->value, 'Value should have been blank'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } - - #[TestDox('named() succeeds')] - public function testNamedSucceeds(): void - { - $field = Field::named('the_field'); - $this->assertNotNull($field, 'The field should not have been null'); - $this->assertEquals('the_field', $field->fieldName, 'Field name not filled correctly'); - $this->assertEquals(Op::Equal, $field->op, 'Operation not filled correctly'); - $this->assertEquals('', $field->value, 'Value should have been blank'); - $this->assertEquals('', $field->paramName, 'Parameter name should have been blank'); - } -} diff --git a/tests/unit/ModeTest.php b/tests/unit/ModeTest.php deleted file mode 100644 index 0987bcd..0000000 --- a/tests/unit/ModeTest.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit; - -use BitBadger\PDODocument\{DocumentException, Mode}; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Mode enumeration - */ -#[TestDox('Mode (Unit tests)')] -class ModeTest extends TestCase -{ - #[TestDox('deriveFromDSN() succeeds for PostgreSQL')] - public function testDeriveFromDSNSucceedsForPostgreSQL(): void - { - $this->assertEquals(Mode::PgSQL, Mode::deriveFromDSN('pgsql:Host=localhost'), 'PostgreSQL mode incorrect'); - } - - #[TestDox('deriveFromDSN() succeeds for SQLite')] - public function testDeriveFromDSNSucceedsForSQLite(): void - { - $this->assertEquals(Mode::SQLite, Mode::deriveFromDSN('sqlite:data.db'), 'SQLite mode incorrect'); - } - - #[TestDox('deriveFromDSN() fails for MySQL')] - public function testDeriveFromDSNFailsForMySQL(): void - { - $this->expectException(DocumentException::class); - Mode::deriveFromDSN('mysql:Host=localhost'); - } -} diff --git a/tests/unit/OpTest.php b/tests/unit/OpTest.php deleted file mode 100644 index 380d24f..0000000 --- a/tests/unit/OpTest.php +++ /dev/null @@ -1,86 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit; - -use BitBadger\PDODocument\Op; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Op enumeration - */ -#[TestDox('Op (Unit tests)')] -class OpTest extends TestCase -{ - #[TestDox('toSQL() succeeds for Equal')] - public function testToSQLSucceedsForEqual(): void - { - $this->assertEquals('=', Op::Equal->toSQL(), 'Equal SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for Greater')] - public function testToSQLSucceedsForGreater(): void - { - $this->assertEquals('>', Op::Greater->toSQL(), 'Greater SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for GreaterOrEqual')] - public function testToSQLSucceedsForGreaterOrEqual(): void - { - $this->assertEquals('>=', Op::GreaterOrEqual->toSQL(), 'GreaterOrEqual SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for Less')] - public function testToSQLSucceedsForLess(): void - { - $this->assertEquals('<', Op::Less->toSQL(), 'Less SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for LessOrEqual')] - public function testToSQLSucceedsForLessOrEqual(): void - { - $this->assertEquals('<=', Op::LessOrEqual->toSQL(), 'LessOrEqual SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for NotEqual')] - public function testToSQLSucceedsForNotEqual(): void - { - $this->assertEquals('<>', Op::NotEqual->toSQL(), 'NotEqual SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for Between')] - public function testToSQLSucceedsForBetween(): void - { - $this->assertEquals('BETWEEN', Op::Between->toSQL(), 'Between SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for In')] - public function testToSQLSucceedsForIn(): void - { - $this->assertEquals('IN', Op::In->toSQL(), 'In SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for InArray')] - public function testToSQLSucceedsForInArray(): void - { - $this->assertEquals('??|', Op::InArray->toSQL(), 'InArray SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for Exists')] - public function testToSQLSucceedsForExists(): void - { - $this->assertEquals('IS NOT NULL', Op::Exists->toSQL(), 'Exists SQL operator incorrect'); - } - - #[TestDox('toSQL() succeeds for NotExists')] - public function testToSQLSucceedsForNEX(): void - { - $this->assertEquals('IS NULL', Op::NotExists->toSQL(), 'NotExists SQL operator incorrect'); - } -} diff --git a/tests/unit/ParametersTest.php b/tests/unit/ParametersTest.php deleted file mode 100644 index 68da6d9..0000000 --- a/tests/unit/ParametersTest.php +++ /dev/null @@ -1,134 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit; - -use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Parameters}; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; -use stdClass; -use Test\{PjsonDocument, PjsonId}; - -/** - * Unit tests for the Parameters class - */ -#[TestDox('Parameters (Unit tests)')] -class ParametersTest extends TestCase -{ - #[TestDox('id() succeeds with string')] - public function testIdSucceedsWithString(): void - { - $this->assertEquals([':id' => 'key'], Parameters::id('key'), 'ID parameter not constructed correctly'); - } - - #[TestDox('id() succeeds with non string')] - public function testIdSucceedsWithNonString(): void - { - $this->assertEquals([':id' => '7'], Parameters::id(7), 'ID parameter not constructed correctly'); - } - - #[TestDox('json() succeeds for array')] - public function testJsonSucceedsForArray(): void - { - $this->assertEquals([':it' => '{"id":18,"url":"https://www.unittest.com"}'], - Parameters::json(':it', ['id' => 18, 'url' => 'https://www.unittest.com']), - 'JSON parameter not constructed correctly'); - } - - #[TestDox('json() succeeds for array with empty array parameter')] - public function testJsonSucceedsForArrayWithEmptyArrayParameter(): void - { - $this->assertEquals([':it' => '{"id":18,"urls":[]}'], Parameters::json(':it', ['id' => 18, 'urls' => []]), - 'JSON parameter not constructed correctly'); - } - - #[TestDox('json() succeeds for 1D array with empty array parameter')] - public function testJsonSucceedsFor1DArrayWithEmptyArrayParameter(): void - { - $this->assertEquals([':it' => '{"urls":[]}'], Parameters::json(':it', ['urls' => []]), - 'JSON parameter not constructed correctly'); - } - - #[TestDox('json() succeeds for stdClass')] - public function testJsonSucceedsForStdClass(): void - { - $obj = new stdClass(); - $obj->id = 19; - $obj->url = 'https://testhere.info'; - $this->assertEquals([':it' => '{"id":19,"url":"https://testhere.info"}'], Parameters::json(':it', $obj), - 'JSON parameter not constructed correctly'); - } - - #[TestDox('json() succeeds for Pjson class')] - public function testJsonSucceedsForPjsonClass(): void - { - $this->assertEquals([':it' => '{"id":"999","name":"a test","num_value":98}'], - Parameters::json(':it', new PjsonDocument(new PjsonId('999'), 'a test', 98, 'nothing')), - 'JSON parameter not constructed correctly'); - } - - #[TestDox('json() succeeds for array of Pjson class')] - public function testJsonSucceedsForArrayOfPjsonClass(): void - { - $this->assertEquals([':it' => '{"pjson":[{"id":"997","name":"another test","num_value":94}]}'], - Parameters::json(':it', - ['pjson' => [new PjsonDocument(new PjsonId('997'), 'another test', 94, 'nothing')]]), - 'JSON parameter not constructed correctly'); - } - - #[TestDox('nameFields() succeeds')] - public function testNameFieldsSucceeds(): void - { - $named = [Field::equal('it', 17), Field::equal('also', 22, ':also'), Field::equal('other', 24)]; - Parameters::nameFields($named); - $this->assertCount(3, $named, 'There should be 3 parameters in the array'); - $this->assertEquals(':field0', $named[0]->paramName, 'Parameter 1 not named correctly'); - $this->assertEquals(':also', $named[1]->paramName, 'Parameter 2 not named correctly'); - $this->assertEquals(':field2', $named[2]->paramName, 'Parameter 3 not named correctly'); - } - - #[TestDox('addFields() succeeds')] - public function testAddFieldsSucceeds(): void - { - $this->assertEquals([':a' => 1, ':b' => 'two', ':z' => 18], - Parameters::addFields([Field::equal('b', 'two', ':b'), Field::equal('z', 18, ':z')], [':a' => 1]), - 'Field parameters not added correctly'); - } - - #[TestDox('fieldNames() succeeds for PostgreSQL')] - public function testFieldNamesSucceedsForPostgreSQL(): void - { - try { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals([':names' => "{one,two,seven}"], - Parameters::fieldNames(':names', ['one', 'two', 'seven']), 'Field name parameters not correct'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('fieldNames() succeeds for SQLite')] - public function testFieldNamesSucceedsForSQLite(): void - { - try { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals([':it0' => '$.test', ':it1' => '$.unit', ':it2' => '$.wow'], - Parameters::fieldNames(':it', ['test', 'unit', 'wow']), 'Field name parameters not correct'); - } finally { - Configuration::overrideMode(null); - } - } - - #[TestDox('fieldNames() fails when mode not set')] - public function testFieldNamesFailsWhenModeNotSet(): void - { - $this->expectException(DocumentException::class); - Configuration::overrideMode(null); - Parameters::fieldNames('', []); - } -}