diff --git a/composer.json b/composer.json index dd1f062..560909d 100644 --- a/composer.json +++ b/composer.json @@ -37,37 +37,26 @@ }, "require-dev": { "automattic/vipwpcs": "^3.0", - "brain/monkey": "^2.6", "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "phpcompatibility/phpcompatibility-wp": "^3.0.0-alpha", "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^2.1.22", "phpstan/phpstan-deprecation-rules": "^2.0.3", "phpstan/phpstan-phpunit": "^2.0.3", - "phpunit/phpunit": "^11.0", + "phpstan/phpstan": "^2.1.22", "slevomat/coding-standard": "^8.0", "squizlabs/php_codesniffer": "^3.9", "szepeviktor/phpstan-wordpress": "^2.0.2", "wp-coding-standards/wpcs": "^3.1", - "wpackagist-plugin/plugin-check": "~1.6.0", - "yoast/phpunit-polyfills": "^3.0" + "wpackagist-plugin/plugin-check": "~1.6.0" }, "autoload": { "psr-4": { "Core_Carousel\\": "inc/" } }, - "autoload-dev": { - "psr-4": { - "Core_Carousel\\Tests\\": "tests/php/" - } - }, "scripts": { "format": "phpcbf", "lint": "phpcs", - "phpstan": "phpstan analyse --memory-limit=2G", - "test": "phpunit", - "test:unit": "phpunit --testsuite unit", - "test:coverage": "phpunit --coverage-html tests/_output/coverage" + "phpstan": "phpstan analyse --memory-limit=2G" } } diff --git a/composer.lock b/composer.lock index 719a5fd..d486c94 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": "c807d59c2478e04aa04acd36971c41e8", + "content-hash": "074cbb3002be39e767760242c625626e", "packages": [ { "name": "scrivo/highlight.php", @@ -86,54 +86,6 @@ } ], "packages-dev": [ - { - "name": "antecedent/patchwork", - "version": "2.2.3", - "source": { - "type": "git", - "url": "https://github.com/antecedent/patchwork.git", - "reference": "8b6b235f405af175259c8f56aea5fc23ab9f03ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/antecedent/patchwork/zipball/8b6b235f405af175259c8f56aea5fc23ab9f03ce", - "reference": "8b6b235f405af175259c8f56aea5fc23ab9f03ce", - "shasum": "" - }, - "require": { - "php": ">=7.1.0" - }, - "require-dev": { - "phpunit/phpunit": ">=4" - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ignas Rudaitis", - "email": "ignas.rudaitis@gmail.com" - } - ], - "description": "Method redefinition (monkey-patching) functionality for PHP.", - "homepage": "https://antecedent.github.io/patchwork/", - "keywords": [ - "aop", - "aspect", - "interception", - "monkeypatching", - "redefinition", - "runkit", - "testing" - ], - "support": { - "issues": "https://github.com/antecedent/patchwork/issues", - "source": "https://github.com/antecedent/patchwork/tree/2.2.3" - }, - "time": "2025-09-17T09:00:56+00:00" - }, { "name": "automattic/vipwpcs", "version": "3.0.1", @@ -188,76 +140,6 @@ }, "time": "2024-05-10T20:31:09+00:00" }, - { - "name": "brain/monkey", - "version": "2.7.0", - "source": { - "type": "git", - "url": "https://github.com/Brain-WP/BrainMonkey.git", - "reference": "ea3aeb3d559ba3c0930b3f4d210b665a4c044d83" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Brain-WP/BrainMonkey/zipball/ea3aeb3d559ba3c0930b3f4d210b665a4c044d83", - "reference": "ea3aeb3d559ba3c0930b3f4d210b665a4c044d83", - "shasum": "" - }, - "require": { - "antecedent/patchwork": "^2.1.17", - "mockery/mockery": "~1.3.6 || ~1.4.4 || ~1.5.1 || ^1.6.10", - "php": ">=5.6.0" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0.0", - "phpcompatibility/php-compatibility": "^9.3.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.49 || ^9.6.30" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev", - "dev-version/1": "1.x-dev" - } - }, - "autoload": { - "files": [ - "inc/api.php" - ], - "psr-4": { - "Brain\\Monkey\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Giuseppe Mazzapica", - "email": "giuseppe.mazzapica@gmail.com", - "homepage": "https://gmazzap.me", - "role": "Developer" - } - ], - "description": "Mocking utility for PHP functions and WordPress plugin API", - "keywords": [ - "Monkey Patching", - "interception", - "mock", - "mock functions", - "mockery", - "patchwork", - "redefinition", - "runkit", - "test", - "testing" - ], - "support": { - "issues": "https://github.com/Brain-WP/BrainMonkey/issues", - "source": "https://github.com/Brain-WP/BrainMonkey" - }, - "time": "2026-02-05T09:22:14+00:00" - }, { "name": "composer/installers", "version": "v2.3.0", @@ -501,2520 +383,706 @@ "time": "2025-11-11T04:32:07+00:00" }, { - "name": "hamcrest/hamcrest-php", - "version": "v2.1.1", + "name": "php-stubs/wordpress-stubs", + "version": "v6.9.0", "source": { "type": "git", - "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + "url": "https://github.com/php-stubs/wordpress-stubs.git", + "reference": "5171cb6650e6c583a96943fd6ea0dfa3e1089a8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", - "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/5171cb6650e6c583a96943fd6ea0dfa3e1089a8a", + "reference": "5171cb6650e6c583a96943fd6ea0dfa3e1089a8a", "shasum": "" }, - "require": { - "php": "^7.4|^8.0" - }, - "replace": { - "cordoval/hamcrest-php": "*", - "davedevelopment/hamcrest-php": "*", - "kodova/hamcrest-php": "*" + "conflict": { + "phpdocumentor/reflection-docblock": "5.6.1" }, "require-dev": { - "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "nikic/php-parser": "^5.5", + "php": "^7.4 || ^8.0", + "php-stubs/generator": "^0.8.3", + "phpdocumentor/reflection-docblock": "^5.4.1", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^9.5", + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.1.1", + "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" }, - "autoload": { - "classmap": [ - "hamcrest" - ] + "suggest": { + "paragonie/sodium_compat": "Pure PHP implementation of libsodium", + "symfony/polyfill-php80": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" }, + "type": "library", "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "description": "This is the PHP port of Hamcrest Matchers", + "description": "WordPress function and class declaration stubs for static analysis.", + "homepage": "https://github.com/php-stubs/wordpress-stubs", "keywords": [ - "test" + "PHPStan", + "static analysis", + "wordpress" ], "support": { - "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + "issues": "https://github.com/php-stubs/wordpress-stubs/issues", + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.9.0" }, - "time": "2025-04-30T06:54:44+00:00" + "time": "2025-12-03T23:06:24+00:00" }, { - "name": "mockery/mockery", - "version": "1.6.12", + "name": "phpcompatibility/php-compatibility", + "version": "10.0.0-alpha2", "source": { "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "e0f0e5a3dc819a4a0f8d679a0f2453d941976e18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", - "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/e0f0e5a3dc819a4a0f8d679a0f2453d941976e18", + "reference": "e0f0e5a3dc819a4a0f8d679a0f2453d941976e18", "shasum": "" }, "require": { - "hamcrest/hamcrest-php": "^2.0.1", - "lib-pcre": ">=7.0", - "php": ">=7.3" + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.1.2", + "squizlabs/php_codesniffer": "^3.13.3 || ^4.0" }, - "conflict": { - "phpunit/phpunit": "<8.0" + "replace": { + "wimg/php-compatibility": "*" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.17", - "symplify/easy-coding-standard": "^12.1.14" + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "phpcsstandards/phpcsdevtools": "^1.2.3", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4 || ^10.5.32 || ^11.3.3", + "yoast/phpunit-polyfills": "^1.1.5 || ^2.0.5 || ^3.1.0" }, - "type": "library", - "autoload": { - "files": [ - "library/helpers.php", - "library/Mockery.php" - ], - "psr-4": { - "Mockery\\": "library/Mockery" + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev", + "dev-develop": "10.x-dev" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "https://github.com/padraic", - "role": "Author" + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" }, { - "name": "Dave Marshall", - "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "https://davedevelopment.co.uk", - "role": "Developer" + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" }, { - "name": "Nathanael Esayeas", - "email": "nathanael.esayeas@protonmail.com", - "homepage": "https://github.com/ghostwriter", - "role": "Lead Developer" + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" } ], - "description": "Mockery is a simple yet flexible PHP mock object framework", - "homepage": "https://github.com/mockery/mockery", + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "https://techblog.wimgodden.be/tag/codesniffer/", "keywords": [ - "BDD", - "TDD", - "library", - "mock", - "mock objects", - "mockery", - "stub", - "test", - "test double", - "testing" + "compatibility", + "phpcs", + "standards", + "static analysis" ], "support": { - "docs": "https://docs.mockery.io/", - "issues": "https://github.com/mockery/mockery/issues", - "rss": "https://github.com/mockery/mockery/releases.atom", - "security": "https://github.com/mockery/mockery/security/advisories", - "source": "https://github.com/mockery/mockery" + "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibility/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibility" }, - "time": "2024-05-16T03:13:13+00:00" + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" + } + ], + "time": "2025-11-28T11:36:33+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.13.4", + "name": "phpcompatibility/phpcompatibility-paragonie", + "version": "2.0.0-alpha2", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", + "reference": "7a979711c87d8202b52f56c56bd719d09d8ed7f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/7a979711c87d8202b52f56c56bd719d09d8ed7f5", + "reference": "7a979711c87d8202b52f56c56bd719d09d8ed7f5", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" + "phpcompatibility/php-compatibility": "^10.0@dev" }, "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } + "paragonie/random_compat": "dev-master", + "paragonie/sodium_compat": "dev-master" }, + "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } ], - "description": "Create deep copies (clones) of your objects", + "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "homepage": "http://phpcompatibility.com/", "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "compatibility", + "paragonie", + "phpcs", + "polyfill", + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2025-08-01T08:46:24+00:00" + "time": "2025-11-29T13:09:49+00:00" }, { - "name": "nikic/php-parser", - "version": "v5.7.0", + "name": "phpcompatibility/phpcompatibility-wp", + "version": "3.0.0-alpha2", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", + "reference": "bd53f24e7528422ac51d64dc8d53e8d4c4a877b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/bd53f24e7528422ac51d64dc8d53e8d4c4a877b3", + "reference": "bd53f24e7528422ac51d64dc8d53e8d4c4a877b3", "shasum": "" }, "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } + "phpcompatibility/php-compatibility": "^10.0@dev", + "phpcompatibility/phpcompatibility-paragonie": "^2.0@dev" }, + "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Nikita Popov" + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" } ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" - }, - "time": "2025-12-06T11:56:16+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "php-stubs/wordpress-stubs", - "version": "v6.9.1", - "source": { - "type": "git", - "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "f12220f303e0d7c0844c0e5e957b0c3cee48d2f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/f12220f303e0d7c0844c0e5e957b0c3cee48d2f7", - "reference": "f12220f303e0d7c0844c0e5e957b0c3cee48d2f7", - "shasum": "" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "5.6.1" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "nikic/php-parser": "^5.5", - "php": "^7.4 || ^8.0", - "php-stubs/generator": "^0.8.3", - "phpdocumentor/reflection-docblock": "^6.0", - "phpstan/phpstan": "^2.1", - "phpunit/phpunit": "^9.5", - "symfony/polyfill-php80": "*", - "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.1.1", - "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" - }, - "suggest": { - "paragonie/sodium_compat": "Pure PHP implementation of libsodium", - "symfony/polyfill-php80": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "WordPress function and class declaration stubs for static analysis.", - "homepage": "https://github.com/php-stubs/wordpress-stubs", - "keywords": [ - "PHPStan", - "static analysis", - "wordpress" - ], - "support": { - "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.9.1" - }, - "time": "2026-02-03T19:29:21+00:00" - }, - { - "name": "phpcompatibility/php-compatibility", - "version": "10.0.0-alpha2", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "e0f0e5a3dc819a4a0f8d679a0f2453d941976e18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/e0f0e5a3dc819a4a0f8d679a0f2453d941976e18", - "reference": "e0f0e5a3dc819a4a0f8d679a0f2453d941976e18", - "shasum": "" - }, - "require": { - "php": ">=5.4", - "phpcsstandards/phpcsutils": "^1.1.2", - "squizlabs/php_codesniffer": "^3.13.3 || ^4.0" - }, - "replace": { - "wimg/php-compatibility": "*" - }, - "require-dev": { - "php-parallel-lint/php-console-highlighter": "^1.0.0", - "php-parallel-lint/php-parallel-lint": "^1.4.0", - "phpcsstandards/phpcsdevcs": "^1.2.0", - "phpcsstandards/phpcsdevtools": "^1.2.3", - "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4 || ^10.5.32 || ^11.3.3", - "yoast/phpunit-polyfills": "^1.1.5 || ^2.0.5 || ^3.1.0" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "9.x-dev", - "dev-develop": "10.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Wim Godden", - "homepage": "https://github.com/wimg", - "role": "lead" - }, - { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", - "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" - } - ], - "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", - "homepage": "https://techblog.wimgodden.be/tag/codesniffer/", - "keywords": [ - "compatibility", - "phpcs", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", - "security": "https://github.com/PHPCompatibility/PHPCompatibility/security/policy", - "source": "https://github.com/PHPCompatibility/PHPCompatibility" - }, - "funding": [ - { - "url": "https://github.com/PHPCompatibility", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcompatibility", - "type": "thanks_dev" - } - ], - "time": "2025-11-28T11:36:33+00:00" - }, - { - "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "2.0.0-alpha2", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "7a979711c87d8202b52f56c56bd719d09d8ed7f5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/7a979711c87d8202b52f56c56bd719d09d8ed7f5", - "reference": "7a979711c87d8202b52f56c56bd719d09d8ed7f5", - "shasum": "" - }, - "require": { - "phpcompatibility/php-compatibility": "^10.0@dev" - }, - "require-dev": { - "paragonie/random_compat": "dev-master", - "paragonie/sodium_compat": "dev-master" - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Wim Godden", - "role": "lead" - }, - { - "name": "Juliette Reinders Folmer", - "role": "lead" - } - ], - "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", - "homepage": "http://phpcompatibility.com/", - "keywords": [ - "compatibility", - "paragonie", - "phpcs", - "polyfill", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", - "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy", - "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" - }, - "funding": [ - { - "url": "https://github.com/PHPCompatibility", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcompatibility", - "type": "thanks_dev" - } - ], - "time": "2025-11-29T13:09:49+00:00" - }, - { - "name": "phpcompatibility/phpcompatibility-wp", - "version": "3.0.0-alpha2", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "bd53f24e7528422ac51d64dc8d53e8d4c4a877b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/bd53f24e7528422ac51d64dc8d53e8d4c4a877b3", - "reference": "bd53f24e7528422ac51d64dc8d53e8d4c4a877b3", - "shasum": "" - }, - "require": { - "phpcompatibility/php-compatibility": "^10.0@dev", - "phpcompatibility/phpcompatibility-paragonie": "^2.0@dev" - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Wim Godden", - "role": "lead" - }, - { - "name": "Juliette Reinders Folmer", - "role": "lead" - } - ], - "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", - "homepage": "http://phpcompatibility.com/", - "keywords": [ - "compatibility", - "phpcs", - "standards", - "static analysis", - "wordpress" - ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", - "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy", - "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" - }, - "funding": [ - { - "url": "https://github.com/PHPCompatibility", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcompatibility", - "type": "thanks_dev" - } - ], - "time": "2025-12-16T13:35:20+00:00" - }, - { - "name": "phpcsstandards/phpcsextra", - "version": "1.5.0", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", - "reference": "b598aa890815b8df16363271b659d73280129101" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101", - "reference": "b598aa890815b8df16363271b659d73280129101", - "shasum": "" - }, - "require": { - "php": ">=5.4", - "phpcsstandards/phpcsutils": "^1.2.0", - "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" - }, - "require-dev": { - "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.4.0", - "phpcsstandards/phpcsdevcs": "^1.2.0", - "phpcsstandards/phpcsdevtools": "^1.2.1", - "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-stable": "1.x-dev", - "dev-develop": "1.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", - "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" - } - ], - "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", - "keywords": [ - "PHP_CodeSniffer", - "phpcbf", - "phpcodesniffer-standard", - "phpcs", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", - "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy", - "source": "https://github.com/PHPCSStandards/PHPCSExtra" - }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcsstandards", - "type": "thanks_dev" - } - ], - "time": "2025-11-12T23:06:57+00:00" - }, - { - "name": "phpcsstandards/phpcsutils", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", - "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", - "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" - }, - "require-dev": { - "ext-filter": "*", - "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.4.0", - "phpcsstandards/phpcsdevcs": "^1.2.0", - "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-stable": "1.x-dev", - "dev-develop": "1.x-dev" - } - }, - "autoload": { - "classmap": [ - "PHPCSUtils/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", - "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" - } - ], - "description": "A suite of utility functions for use with PHP_CodeSniffer", - "homepage": "https://phpcsutils.com/", - "keywords": [ - "PHP_CodeSniffer", - "phpcbf", - "phpcodesniffer-standard", - "phpcs", - "phpcs3", - "phpcs4", - "standards", - "static analysis", - "tokens", - "utility" - ], - "support": { - "docs": "https://phpcsutils.com/", - "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", - "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", - "source": "https://github.com/PHPCSStandards/PHPCSUtils" - }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcsstandards", - "type": "thanks_dev" - } - ], - "time": "2025-12-08T14:27:58+00:00" - }, - { - "name": "phpstan/extension-installer", - "version": "1.4.3", - "source": { - "type": "git", - "url": "https://github.com/phpstan/extension-installer.git", - "reference": "85e90b3942d06b2326fba0403ec24fe912372936" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", - "reference": "85e90b3942d06b2326fba0403ec24fe912372936", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.0", - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.9.0 || ^2.0" - }, - "require-dev": { - "composer/composer": "^2.0", - "php-parallel-lint/php-parallel-lint": "^1.2.0", - "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PHPStan\\ExtensionInstaller\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPStan\\ExtensionInstaller\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Composer plugin for automatic installation of PHPStan extensions", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpstan/extension-installer/issues", - "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" - }, - "time": "2024-09-04T20:21:43+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "2.3.2", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", - "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^5.3.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "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/2.3.2" - }, - "time": "2026-01-25T14:56:51+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "2.1.38", - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dfaf1f530e1663aa167bc3e52197adb221582629", - "reference": "dfaf1f530e1663aa167bc3e52197adb221582629", - "shasum": "" - }, - "require": { - "php": "^7.4|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - } - ], - "time": "2026-01-30T17:12:46+00:00" - }, - { - "name": "phpstan/phpstan-deprecation-rules", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "468e02c9176891cc901143da118f09dc9505fc2f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/468e02c9176891cc901143da118f09dc9505fc2f", - "reference": "468e02c9176891cc901143da118f09dc9505fc2f", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.15" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^9.6" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", - "support": { - "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.3" - }, - "time": "2025-05-14T10:56:57+00:00" - }, - { - "name": "phpstan/phpstan-phpunit", - "version": "2.0.12", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "e4c5a22bf43d3d2bd5a780ad261a622ff62c49a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/e4c5a22bf43d3d2bd5a780ad261a622ff62c49a4", - "reference": "e4c5a22bf43d3d2bd5a780ad261a622ff62c49a4", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.32" - }, - "conflict": { - "phpunit/phpunit": "<7.0" - }, - "require-dev": { - "nikic/php-parser": "^5", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-deprecation-rules": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPUnit extensions and rules for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.12" - }, - "time": "2026-01-22T13:40:00+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "11.0.12", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56", - "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^5.7.0", - "php": ">=8.2", - "phpunit/php-file-iterator": "^5.1.0", - "phpunit/php-text-template": "^4.0.1", - "sebastian/code-unit-reverse-lookup": "^4.0.1", - "sebastian/complexity": "^4.0.1", - "sebastian/environment": "^7.2.1", - "sebastian/lines-of-code": "^3.0.1", - "sebastian/version": "^5.0.2", - "theseer/tokenizer": "^1.3.1" - }, - "require-dev": { - "phpunit/phpunit": "^11.5.46" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "11.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", - "type": "tidelift" - } - ], - "time": "2025-12-24T07:01:01+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "5.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903", - "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", - "type": "tidelift" - } - ], - "time": "2026-02-02T13:52:54+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "5.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", - "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^11.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:07:44+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", - "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:08:43+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "7.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", - "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:09:35+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "11.5.51", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ad14159f92910b0f0e3928c13e9b2077529de091" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ad14159f92910b0f0e3928c13e9b2077529de091", - "reference": "ad14159f92910b0f0e3928c13e9b2077529de091", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.12", - "phpunit/php-file-iterator": "^5.1.1", - "phpunit/php-invoker": "^5.0.1", - "phpunit/php-text-template": "^4.0.1", - "phpunit/php-timer": "^7.0.1", - "sebastian/cli-parser": "^3.0.2", - "sebastian/code-unit": "^3.0.3", - "sebastian/comparator": "^6.3.3", - "sebastian/diff": "^6.0.2", - "sebastian/environment": "^7.2.1", - "sebastian/exporter": "^6.3.2", - "sebastian/global-state": "^7.0.2", - "sebastian/object-enumerator": "^6.0.1", - "sebastian/recursion-context": "^6.0.3", - "sebastian/type": "^5.1.3", - "sebastian/version": "^5.0.2", - "staabm/side-effects-detector": "^1.0.5" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "11.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.51" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2026-02-05T07:59:30+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", - "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:41:36+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", - "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2025-03-19T07:56:08+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "183a9b2632194febd219bb9246eee421dad8d45e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", - "reference": "183a9b2632194febd219bb9246eee421dad8d45e", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:45:54+00:00" - }, - { - "name": "sebastian/comparator", - "version": "6.3.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", - "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.2", - "sebastian/diff": "^6.0", - "sebastian/exporter": "^6.0" - }, - "require-dev": { - "phpunit/phpunit": "^11.4" - }, - "suggest": { - "ext-bcmath": "For comparing BcMath\\Number objects" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", - "type": "tidelift" - } - ], - "time": "2026-01-24T09:26:40+00:00" - }, - { - "name": "sebastian/complexity", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", - "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:49:50+00:00" - }, - { - "name": "sebastian/diff", - "version": "6.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", - "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T04:53:05+00:00" - }, - { - "name": "sebastian/environment", - "version": "7.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", - "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", + "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "homepage": "http://phpcompatibility.com/", "keywords": [ - "Xdebug", - "environment", - "hhvm" + "compatibility", + "phpcs", + "standards", + "static analysis", + "wordpress" ], "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCompatibility", "type": "github" }, { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" + "url": "https://github.com/jrfnl", + "type": "github" }, { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" }, { - "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", - "type": "tidelift" + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2025-05-21T11:55:47+00:00" + "time": "2025-12-16T13:35:20+00:00" }, { - "name": "sebastian/exporter", - "version": "6.3.2", + "name": "phpcsstandards/phpcsextra", + "version": "1.5.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" + "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", + "reference": "b598aa890815b8df16363271b659d73280129101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", - "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101", + "reference": "b598aa890815b8df16363271b659d73280129101", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=8.2", - "sebastian/recursion-context": "^6.0" + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.2.0", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" }, "require-dev": { - "phpunit/phpunit": "^11.3" + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "phpcsstandards/phpcsdevtools": "^1.2.1", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, - "type": "library", + "type": "phpcodesniffer-standard", "extra": { "branch-alias": { - "dev-main": "6.3-dev" + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" } }, - "autoload": { - "classmap": [ - "src/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" }, { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", + "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", "keywords": [ - "export", - "exporter" + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2" + "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", + "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSExtra" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCSStandards", "type": "github" }, { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" + "url": "https://github.com/jrfnl", + "type": "github" }, { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" }, { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", - "type": "tidelift" + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2025-09-24T06:12:51+00:00" + "time": "2025-11-12T23:06:57+00:00" }, { - "name": "sebastian/global-state", - "version": "7.0.2", + "name": "phpcsstandards/phpcsutils", + "version": "1.2.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", - "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", + "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", "shasum": "" }, "require": { - "php": ">=8.2", - "sebastian/object-reflector": "^4.0", - "sebastian/recursion-context": "^6.0" + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" }, "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^11.0" + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" }, - "type": "library", + "type": "phpcodesniffer-standard", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" } }, "autoload": { "classmap": [ - "src/" + "PHPCSUtils/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" } ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", "keywords": [ - "global state" + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs3", + "phpcs4", + "standards", + "static analysis", + "tokens", + "utility" ], "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCSStandards", "type": "github" - } - ], - "time": "2024-07-03T04:57:36+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", - "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" - }, - "funding": [ + }, { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/jrfnl", "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-07-03T04:58:38+00:00" + "time": "2025-12-08T14:27:58+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "6.0.1", + "name": "phpstan/extension-installer", + "version": "1.4.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", - "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936", "shasum": "" }, "require": { - "php": ">=8.2", - "sebastian/object-reflector": "^4.0", - "sebastian/recursion-context": "^6.0" + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0 || ^2.0" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" }, - "type": "library", + "type": "composer-plugin", "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } + "class": "PHPStan\\ExtensionInstaller\\Plugin" }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } + "description": "Composer plugin for automatic installation of PHPStan extensions", + "keywords": [ + "dev", + "static analysis" ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:00:13+00:00" + "time": "2024-09-04T20:21:43+00:00" }, { - "name": "sebastian/object-reflector", - "version": "4.0.1", + "name": "phpstan/phpdoc-parser", + "version": "2.3.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", - "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/16dbf9937da8d4528ceb2145c9c7c0bd29e26374", + "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374", "shasum": "" }, "require": { - "php": ">=8.2" + "php": "^7.4 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } + "MIT" ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.1" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-07-03T05:01:32+00:00" + "time": "2026-01-12T11:33:04+00:00" }, { - "name": "sebastian/recursion-context", - "version": "6.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" - }, + "name": "phpstan/phpstan", + "version": "2.1.33", "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", - "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", + "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", "shasum": "" }, "require": { - "php": ">=8.2" + "php": "^7.4|^8.0" }, - "require-dev": { - "phpunit/phpunit": "^11.3" + "conflict": { + "phpstan/phpstan-shim": "*" }, + "bin": [ + "phpstan", + "phpstan.phar" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/ondrejmirtes", "type": "github" }, { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", - "type": "tidelift" + "url": "https://github.com/phpstan", + "type": "github" } ], - "time": "2025-08-13T04:42:22+00:00" + "time": "2025-12-05T10:24:31+00:00" }, { - "name": "sebastian/type", - "version": "5.1.3", + "name": "phpstan/phpstan-deprecation-rules", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" + "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", + "reference": "468e02c9176891cc901143da118f09dc9505fc2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", - "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/468e02c9176891cc901143da118f09dc9505fc2f", + "reference": "468e02c9176891cc901143da118f09dc9505fc2f", "shasum": "" }, "require": { - "php": ">=8.2" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.15" }, "require-dev": { - "phpunit/phpunit": "^11.3" + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" }, - "type": "library", + "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-main": "5.1-dev" + "phpstan": { + "includes": [ + "rules.neon" + ] } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } + "MIT" ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" + "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.3" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/type", - "type": "tidelift" - } - ], - "time": "2025-08-09T06:55:48+00:00" + "time": "2025-05-14T10:56:57+00:00" }, { - "name": "sebastian/version", - "version": "5.0.2", + "name": "phpstan/phpstan-phpunit", + "version": "2.0.11", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + "url": "https://github.com/phpstan/phpstan-phpunit.git", + "reference": "5e30669bef866eff70db8b58d72a5c185aa82414" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", - "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/5e30669bef866eff70db8b58d72a5c185aa82414", + "reference": "5e30669bef866eff70db8b58d72a5c185aa82414", "shasum": "" }, "require": { - "php": ">=8.2" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.32" }, - "type": "library", + "conflict": { + "phpunit/phpunit": "<7.0" + }, + "require-dev": { + "nikic/php-parser": "^5", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6" + }, + "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-main": "5.0-dev" + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } + "MIT" ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", + "description": "PHPUnit extensions and rules for PHPStan", "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + "issues": "https://github.com/phpstan/phpstan-phpunit/issues", + "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.11" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-10-09T05:16:32+00:00" + "time": "2025-12-19T09:05:35+00:00" }, { "name": "sirbrillig/phpcs-variable-analysis", @@ -3216,58 +1284,6 @@ ], "time": "2025-11-04T16:30:35+00:00" }, - { - "name": "staabm/side-effects-detector", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/staabm/side-effects-detector.git", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^1.12.6", - "phpunit/phpunit": "^9.6.21", - "symfony/var-dumper": "^5.4.43", - "tomasvotruba/type-coverage": "1.0.0", - "tomasvotruba/unused-public": "1.0.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A static analysis tool to detect side effects in PHP code", - "keywords": [ - "static analysis" - ], - "support": { - "issues": "https://github.com/staabm/side-effects-detector/issues", - "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" - }, - "funding": [ - { - "url": "https://github.com/staabm", - "type": "github" - } - ], - "time": "2024-10-20T05:08:20+00:00" - }, { "name": "szepeviktor/phpstan-wordpress", "version": "v2.0.3", @@ -3331,56 +1347,6 @@ }, "time": "2025-09-14T02:58:22+00:00" }, - { - "name": "theseer/tokenizer", - "version": "1.3.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", - "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.3.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2025-11-17T20:03:58+00:00" - }, { "name": "wp-coding-standards/wpcs", "version": "3.3.0", @@ -3464,69 +1430,6 @@ }, "type": "wordpress-plugin", "homepage": "https://wordpress.org/plugins/plugin-check/" - }, - { - "name": "yoast/phpunit-polyfills", - "version": "3.1.2", - "source": { - "type": "git", - "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", - "reference": "9cf2ccd990eadfc4a1e390592d4731e590b2c618" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/9cf2ccd990eadfc4a1e390592d4731e590b2c618", - "reference": "9cf2ccd990eadfc4a1e390592d4731e590b2c618", - "shasum": "" - }, - "require": { - "php": ">=7.0", - "phpunit/phpunit": "^6.4.4 || ^7.0 || ^8.0 || ^9.0 || ^11.0" - }, - "require-dev": { - "php-parallel-lint/php-console-highlighter": "^1.0.0", - "php-parallel-lint/php-parallel-lint": "^1.4.0", - "yoast/yoastcs": "^3.1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.x-dev" - } - }, - "autoload": { - "files": [ - "phpunitpolyfills-autoload.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Team Yoast", - "email": "support@yoast.com", - "homepage": "https://yoast.com" - }, - { - "name": "Contributors", - "homepage": "https://github.com/Yoast/PHPUnit-Polyfills/graphs/contributors" - } - ], - "description": "Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit cross-version compatible tests", - "homepage": "https://github.com/Yoast/PHPUnit-Polyfills", - "keywords": [ - "phpunit", - "polyfill", - "testing" - ], - "support": { - "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", - "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy", - "source": "https://github.com/Yoast/PHPUnit-Polyfills" - }, - "time": "2025-02-09T18:36:24+00:00" } ], "aliases": [], diff --git a/core-carousel.php b/core-carousel.php index 5c177ee..6daaf49 100644 --- a/core-carousel.php +++ b/core-carousel.php @@ -2,9 +2,7 @@ /** * Plugin Name: Core Carousel * Description: Carousel block using Embla and WordPress Interactivity API. - * Plugin URI: https://github.com/rtCamp/core-carousel - * Requires at least: 6.1 - * Requires PHP: 7.4 + * Plugin URI: https://rtcamp.com * Author: rtCamp * Author URI: https://rtcamp.com * License: GPL2 diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 9c127e7..0000000 --- a/jest.config.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Jest configuration for Core Carousel plugin. - * - * Extends @wordpress/scripts default configuration with: - * - Custom test setup for WordPress and Embla mocks - * - Module path aliases for cleaner imports - * - Coverage thresholds to maintain code quality - * - * @see https://jestjs.io/docs/configuration - */ - -const defaultConfig = require( '@wordpress/scripts/config/jest-unit.config' ); - -module.exports = { - ...defaultConfig, - - // Display name for clarity in multi-project setups - displayName: 'core-carousel', - - // Test setup files run after Jest environment is set up - setupFilesAfterEnv: [ - ...( defaultConfig.setupFilesAfterEnv || [] ), - '/tests/js/setup.ts', - ], - - // Module resolution aliases - moduleNameMapper: { - ...defaultConfig.moduleNameMapper, - // Path alias for src directory - '^@/(.*)$': '/src/$1', - // Mock for WordPress Interactivity API (not available in test environment) - '^@wordpress/interactivity$': '/tests/js/__mocks__/wordpress-interactivity.ts', - }, - - // Directories to ignore when searching for tests - testPathIgnorePatterns: [ - '/node_modules/', - '/build/', - '/vendor/', - ], - - // Files to include in coverage reports - collectCoverageFrom: [ - 'src/**/*.{ts,tsx}', - // Exclude type definition files - '!src/**/*.d.ts', - // Exclude barrel exports - '!src/**/index.ts', - // Exclude WordPress block JSON schemas - '!src/**/*.json', - ], - - // Coverage thresholds - fail if coverage drops below these percentages - coverageThreshold: { - global: { - branches: 40, - functions: 40, - lines: 40, - statements: 40, - }, - }, - - // Coverage reporters for different outputs - coverageReporters: [ - 'text', - 'text-summary', - 'lcov', - 'html', - ], - - // Verbose output for CI environments - verbose: process.env.CI === 'true', - - // Timeout for slow tests (useful for integration tests) - testTimeout: 10000, -}; diff --git a/package-lock.json b/package-lock.json index b4313f8..e8501f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,9 +27,6 @@ "devDependencies": { "@commitlint/cli": "20.4.1", "@commitlint/config-conventional": "20.4.1", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.1.0", - "@types/jest": "^29.5.14", "@types/react": "^18.3.27", "@types/react-dom": "^18.3.7", "@types/wordpress__block-editor": "15.0.0", @@ -45,13 +42,6 @@ "npm": "^10.0.0" } }, - "node_modules/@adobe/css-tools": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", - "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", - "dev": true, - "license": "MIT" - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -6728,131 +6718,6 @@ "integrity": "sha512-RwARl+hFwhzy0tg9atWcchLFvoQiOh4rrP7uG2N5E4W80BPCUX0ElcUR9St43fxB9EfjsW2df9Qp+UsTbvQDjA==", "license": "MIT" }, - "node_modules/@testing-library/dom": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", - "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "picocolors": "1.1.1", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/dom/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/@testing-library/dom/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@testing-library/dom/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", - "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "picocolors": "^1.1.1", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@testing-library/react": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", - "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@testing-library/dom": "^10.0.0", - "@types/react": "^18.0.0 || ^19.0.0", - "@types/react-dom": "^18.0.0 || ^19.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", @@ -6881,14 +6746,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -7110,17 +6967,6 @@ "@types/istanbul-lib-report": "*" } }, - "node_modules/@types/jest": { - "version": "29.5.14", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", - "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, "node_modules/@types/jsdom": { "version": "21.1.7", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", @@ -13145,13 +12991,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true, - "license": "MIT" - }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -13771,14 +13610,6 @@ "node": ">=6.0.0" } }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -19739,17 +19570,6 @@ "yallist": "^3.0.2" } }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "lz-string": "bin/bin.js" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", diff --git a/package.json b/package.json index d933fc4..d7d7e69 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,7 @@ "lint:php:fix": "composer run-script format", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", "version": "npm run changelog && git add CHANGELOG.md", - "test:actions": "act", - "test:js": "wp-scripts test-unit-js", - "test:js:watch": "wp-scripts test-unit-js --watch", - "test:js:coverage": "wp-scripts test-unit-js --coverage" + "test:actions": "act" }, "dependencies": { "@wordpress/babel-preset-default": "8.38.0", @@ -45,9 +42,6 @@ "devDependencies": { "@commitlint/cli": "20.4.1", "@commitlint/config-conventional": "20.4.1", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.1.0", - "@types/jest": "^29.5.14", "@types/react": "^18.3.27", "@types/react-dom": "^18.3.7", "@types/wordpress__block-editor": "15.0.0", diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 04adb04..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,27 +0,0 @@ - - - - - tests/php/Unit - - - - - inc - core-carousel.php - - - vendor - tests - - - diff --git a/src/blocks/carousel/__tests__/types.test.ts b/src/blocks/carousel/__tests__/types.test.ts deleted file mode 100644 index efccbb9..0000000 --- a/src/blocks/carousel/__tests__/types.test.ts +++ /dev/null @@ -1,570 +0,0 @@ -/** - * Unit tests for the CarouselAttributes and CarouselContext type definitions. - * - * These tests verify: - * - Type structures are correct and TypeScript compilation passes - * - All valid values for union types are accepted - * - Default and edge case values work correctly - * - Optional properties behave as expected - * - * Note: These are compile-time type checks that also verify runtime behavior. - * - * @package - */ - -import type { CarouselAttributes, CarouselContext } from '../types'; - -describe( 'CarouselAttributes Type', () => { - describe( 'Structure Validation', () => { - it( 'should accept valid complete attributes', () => { - const attributes: CarouselAttributes = { - loop: true, - dragFree: false, - carouselAlign: 'center', - containScroll: 'trimSnaps', - direction: 'ltr', - axis: 'x', - height: '400px', - allowedSlideBlocks: [ 'core/image', 'core/paragraph' ], - autoplay: true, - autoplayDelay: 5000, - autoplayStopOnInteraction: true, - autoplayStopOnMouseEnter: true, - ariaLabel: 'Image carousel', - slideGap: 16, - slidesToScroll: '1', - }; - - expect( attributes ).toBeDefined(); - expect( attributes.loop ).toBe( true ); - expect( attributes.carouselAlign ).toBe( 'center' ); - expect( attributes.direction ).toBe( 'ltr' ); - } ); - - it( 'should have all required properties', () => { - const attributes: CarouselAttributes = { - loop: false, - dragFree: true, - carouselAlign: 'start', - containScroll: 'keepSnaps', - direction: 'rtl', - axis: 'y', - height: '300px', - allowedSlideBlocks: [], - autoplay: false, - autoplayDelay: 3000, - autoplayStopOnInteraction: false, - autoplayStopOnMouseEnter: false, - ariaLabel: '', - slideGap: 0, - slidesToScroll: 'auto', - }; - - // Verify all keys exist - const requiredKeys = [ - 'loop', - 'dragFree', - 'carouselAlign', - 'containScroll', - 'direction', - 'axis', - 'height', - 'allowedSlideBlocks', - 'autoplay', - 'autoplayDelay', - 'autoplayStopOnInteraction', - 'autoplayStopOnMouseEnter', - 'ariaLabel', - 'slideGap', - 'slidesToScroll', - ]; - - requiredKeys.forEach( ( key ) => { - expect( attributes ).toHaveProperty( key ); - } ); - } ); - } ); - - describe( 'Alignment Options', () => { - it.each( [ 'start', 'center', 'end' ] as const )( - 'should accept carouselAlign value: %s', - ( align ) => { - const attributes: Partial< CarouselAttributes > = { - carouselAlign: align, - }; - expect( attributes.carouselAlign ).toBe( align ); - }, - ); - - it( 'should accept optional align property', () => { - const withAlign: Partial< CarouselAttributes > = { - align: 'center', - }; - expect( withAlign.align ).toBe( 'center' ); - - const withoutAlign: Partial< CarouselAttributes > = {}; - expect( withoutAlign.align ).toBeUndefined(); - } ); - } ); - - describe( 'Scroll Containment', () => { - it.each( [ 'trimSnaps', 'keepSnaps' ] as const )( - 'should accept containScroll value: %s', - ( value ) => { - const attributes: Partial< CarouselAttributes > = { - containScroll: value, - }; - expect( attributes.containScroll ).toBe( value ); - }, - ); - } ); - - describe( 'Direction and Axis', () => { - it.each( [ 'ltr', 'rtl' ] as const )( - 'should accept direction value: %s', - ( direction ) => { - const attributes: Partial< CarouselAttributes > = { direction }; - expect( attributes.direction ).toBe( direction ); - }, - ); - - it.each( [ 'x', 'y' ] as const )( - 'should accept axis value: %s', - ( axis ) => { - const attributes: Partial< CarouselAttributes > = { axis }; - expect( attributes.axis ).toBe( axis ); - }, - ); - } ); - - describe( 'Autoplay Configuration', () => { - it( 'should accept autoplay as boolean', () => { - const enabled: Partial< CarouselAttributes > = { autoplay: true }; - const disabled: Partial< CarouselAttributes > = { autoplay: false }; - - expect( enabled.autoplay ).toBe( true ); - expect( disabled.autoplay ).toBe( false ); - } ); - - it( 'should accept valid autoplay delay values', () => { - const delays = [ 0, 1000, 3000, 5000, 10000 ]; - - delays.forEach( ( delay ) => { - const attributes: Partial< CarouselAttributes > = { - autoplayDelay: delay, - }; - expect( attributes.autoplayDelay ).toBe( delay ); - } ); - } ); - } ); - - describe( 'Slide Configuration', () => { - it( 'should accept empty allowedSlideBlocks array', () => { - const attributes: Partial< CarouselAttributes > = { - allowedSlideBlocks: [], - }; - expect( attributes.allowedSlideBlocks ).toHaveLength( 0 ); - } ); - - it( 'should accept multiple block types in allowedSlideBlocks', () => { - const blocks = [ - 'core/image', - 'core/paragraph', - 'core/heading', - 'core/group', - 'core/columns', - ]; - - const attributes: Partial< CarouselAttributes > = { - allowedSlideBlocks: blocks, - }; - - expect( attributes.allowedSlideBlocks ).toHaveLength( 5 ); - expect( attributes.allowedSlideBlocks ).toContain( 'core/image' ); - } ); - - it( 'should accept various slideGap values', () => { - const gaps = [ 0, 8, 16, 24, 32 ]; - - gaps.forEach( ( gap ) => { - const attributes: Partial< CarouselAttributes > = { - slideGap: gap, - }; - expect( attributes.slideGap ).toBe( gap ); - } ); - } ); - - it( 'should accept slidesToScroll as string', () => { - const values = [ '1', '2', '3', 'auto' ]; - - values.forEach( ( value ) => { - const attributes: Partial< CarouselAttributes > = { - slidesToScroll: value, - }; - expect( attributes.slidesToScroll ).toBe( value ); - } ); - } ); - } ); - - describe( 'Accessibility', () => { - it( 'should accept various ariaLabel values', () => { - const labels = [ - 'Image carousel', - 'Product gallery', - 'Testimonial slider', - '', - ]; - - labels.forEach( ( label ) => { - const attributes: Partial< CarouselAttributes > = { - ariaLabel: label, - }; - expect( attributes.ariaLabel ).toBe( label ); - } ); - } ); - } ); - - describe( 'Dimension Configuration', () => { - it( 'should accept various height values', () => { - const heights = [ '100px', '400px', '50vh', '100%', 'auto' ]; - - heights.forEach( ( height ) => { - const attributes: Partial< CarouselAttributes > = { height }; - expect( attributes.height ).toBe( height ); - } ); - } ); - } ); -} ); - -describe( 'CarouselContext Type', () => { - describe( 'Autoplay State', () => { - it( 'should accept context with autoplay disabled', () => { - const context: CarouselContext = { - options: { - loop: false, - align: 'start', - }, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [ { index: 0 }, { index: 1 } ], - canScrollPrev: false, - canScrollNext: true, - ariaLabelPattern: 'Go to slide %d', - }; - - expect( context.autoplay ).toBe( false ); - expect( context.isPlaying ).toBe( false ); - } ); - - it( 'should accept context with autoplay configuration object', () => { - const context: CarouselContext = { - options: { - loop: true, - align: 'center', - }, - autoplay: { - delay: 5000, - stopOnInteraction: true, - stopOnMouseEnter: false, - }, - isPlaying: true, - timerIterationId: 1, - selectedIndex: 2, - scrollSnaps: [ { index: 0 }, { index: 1 }, { index: 2 } ], - canScrollPrev: true, - canScrollNext: true, - ariaLabelPattern: 'Slide %d of 3', - }; - - expect( context.autoplay ).not.toBe( false ); - expect( typeof context.autoplay ).toBe( 'object' ); - - if ( typeof context.autoplay === 'object' ) { - expect( context.autoplay.delay ).toBe( 5000 ); - expect( context.autoplay.stopOnInteraction ).toBe( true ); - expect( context.autoplay.stopOnMouseEnter ).toBe( false ); - } - } ); - } ); - - describe( 'Scroll State Management', () => { - it( 'should track first slide state correctly', () => { - const context: CarouselContext = { - options: { loop: false }, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [ { index: 0 }, { index: 1 }, { index: 2 } ], - canScrollPrev: false, - canScrollNext: true, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.selectedIndex ).toBe( 0 ); - expect( context.canScrollPrev ).toBe( false ); - expect( context.canScrollNext ).toBe( true ); - } ); - - it( 'should track middle slide state correctly', () => { - const context: CarouselContext = { - options: { loop: false }, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 1, - scrollSnaps: [ { index: 0 }, { index: 1 }, { index: 2 } ], - canScrollPrev: true, - canScrollNext: true, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.selectedIndex ).toBe( 1 ); - expect( context.canScrollPrev ).toBe( true ); - expect( context.canScrollNext ).toBe( true ); - } ); - - it( 'should track last slide state correctly', () => { - const context: CarouselContext = { - options: { loop: false }, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 2, - scrollSnaps: [ { index: 0 }, { index: 1 }, { index: 2 } ], - canScrollPrev: true, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.selectedIndex ).toBe( 2 ); - expect( context.canScrollPrev ).toBe( true ); - expect( context.canScrollNext ).toBe( false ); - } ); - - it( 'should handle single slide carousel', () => { - const context: CarouselContext = { - options: {}, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [ { index: 0 } ], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.scrollSnaps ).toHaveLength( 1 ); - expect( context.canScrollPrev ).toBe( false ); - expect( context.canScrollNext ).toBe( false ); - } ); - } ); - - describe( 'Timer and Animation State', () => { - it( 'should track timerIterationId for animation resets', () => { - const context: CarouselContext = { - options: {}, - autoplay: { delay: 3000, stopOnInteraction: true, stopOnMouseEnter: false }, - isPlaying: true, - timerIterationId: 5, - selectedIndex: 0, - scrollSnaps: [ { index: 0 } ], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.timerIterationId ).toBe( 5 ); - - // Simulate slide change incrementing the ID - const updatedContext = { ...context, timerIterationId: 6 }; - expect( updatedContext.timerIterationId ).toBe( 6 ); - } ); - - it( 'should have initial timerIterationId of 0', () => { - const context: CarouselContext = { - options: {}, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.timerIterationId ).toBe( 0 ); - } ); - } ); - - describe( 'Optional Properties', () => { - it( 'should include optional ref property when provided', () => { - const element = document.createElement( 'div' ); - - const context: CarouselContext = { - options: {}, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - ref: element, - }; - - expect( context.ref ).toBe( element ); - expect( context.ref ).toBeInstanceOf( HTMLElement ); - } ); - - it( 'should allow null ref', () => { - const context: CarouselContext = { - options: {}, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - ref: null, - }; - - expect( context.ref ).toBeNull(); - } ); - - it( 'should work without ref property', () => { - const context: CarouselContext = { - options: {}, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.ref ).toBeUndefined(); - } ); - } ); - - describe( 'Embla Options Integration', () => { - it( 'should accept slidesToScroll as number in options', () => { - const context: CarouselContext = { - options: { - loop: true, - slidesToScroll: 2, - }, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.options.slidesToScroll ).toBe( 2 ); - } ); - - it( 'should accept slidesToScroll as "auto" in options', () => { - const context: CarouselContext = { - options: { - loop: true, - slidesToScroll: 'auto', - }, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.options.slidesToScroll ).toBe( 'auto' ); - } ); - } ); - - describe( 'ARIA Label Pattern', () => { - it( 'should accept pattern with placeholder', () => { - const patterns = [ - 'Go to slide %d', - 'Slide %d of 10', - 'View item %d', - '%d', - ]; - - patterns.forEach( ( pattern ) => { - const context: CarouselContext = { - options: {}, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: pattern, - }; - - expect( context.ariaLabelPattern ).toBe( pattern ); - } ); - } ); - } ); - - describe( 'Scroll Snaps Array', () => { - it( 'should accept empty scrollSnaps array', () => { - const context: CarouselContext = { - options: {}, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [], - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.scrollSnaps ).toHaveLength( 0 ); - } ); - - it( 'should accept scrollSnaps with correct index structure', () => { - const scrollSnaps = [ - { index: 0 }, - { index: 1 }, - { index: 2 }, - { index: 3 }, - { index: 4 }, - ]; - - const context: CarouselContext = { - options: {}, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps, - canScrollPrev: false, - canScrollNext: false, - ariaLabelPattern: 'Slide %d', - }; - - expect( context.scrollSnaps ).toHaveLength( 5 ); - context.scrollSnaps.forEach( ( snap, i ) => { - expect( snap.index ).toBe( i ); - } ); - } ); - } ); -} ); diff --git a/src/blocks/carousel/__tests__/view.test.ts b/src/blocks/carousel/__tests__/view.test.ts deleted file mode 100644 index ee8c22a..0000000 --- a/src/blocks/carousel/__tests__/view.test.ts +++ /dev/null @@ -1,775 +0,0 @@ -/** - * Unit tests for the carousel view.ts frontend logic. - * - * Tests cover: - * - Store registration and configuration - * - State getters and their return values - * - Action behaviors (scrollPrev, scrollNext, onDotClick) - * - Callback behaviors (isSlideActive, isDotActive, getDotLabel, initCarousel) - * - Error handling and edge cases - * - Embla Carousel integration - * - * @package - */ - -import { - store, - getContext, - getElement, -} from '@wordpress/interactivity'; - -import EmblaCarousel, { type EmblaCarouselType } from 'embla-carousel'; - -// Symbol key used by the view.ts for Embla instances -const EMBLA_KEY = Symbol.for( 'core-carousel.carousel' ); - -// Type for viewport element with Embla instance attached -type EmblaViewportElement = HTMLElement & { - [ EMBLA_KEY ]?: EmblaCarouselType; -}; - -import type { CarouselContext } from '../types'; - -// Import view to trigger store registration -import '../view'; - -// Get the store config that was passed to store() -const storeCall = ( store as jest.Mock ).mock.calls.find( - ( call: unknown[] ) => call[ 0 ] === 'core-carousel/carousel', -); -const storeConfig = storeCall ? storeCall[ 1 ] : null; - -/** - * Helper to set Embla instance on a viewport element. - * @param viewport The viewport element to attach the Embla instance to. - * @param embla The Embla instance to attach. - */ -const setEmblaOnViewport = ( - viewport: HTMLElement, - embla: Partial< EmblaCarouselType >, -) => { - ( viewport as EmblaViewportElement )[ EMBLA_KEY ] = - embla as EmblaCarouselType; -}; - -/** - * Helper to create mock carousel context with customizable properties. - * @param overrides Partial properties to override in the default context. - */ -const createMockContext = ( - overrides: Partial< CarouselContext > = {}, -): CarouselContext => ( { - options: { loop: true }, - autoplay: false, - isPlaying: false, - timerIterationId: 0, - selectedIndex: 0, - scrollSnaps: [ { index: 0 }, { index: 1 }, { index: 2 } ], - canScrollPrev: true, - canScrollNext: true, - ariaLabelPattern: 'Go to slide %d', - ...overrides, -} ); - -/** - * Helper to create a mock DOM element structure for carousel. - */ -const createMockCarouselDOM = () => { - const viewport = document.createElement( 'div' ); - viewport.className = 'embla'; - - const wrapper = document.createElement( 'div' ); - wrapper.className = 'core-carousel'; - wrapper.appendChild( viewport ); - - const button = document.createElement( 'button' ); - wrapper.appendChild( button ); - - return { wrapper, viewport, button }; -}; - -/** - * Helper to create mock Embla instance with all required methods. - * @param overrides Partial methods to override in the default mock instance. - */ -const createMockEmblaInstance = ( overrides = {} ) => ( { - scrollPrev: jest.fn(), - scrollNext: jest.fn(), - scrollTo: jest.fn(), - on: jest.fn(), - off: jest.fn(), - destroy: jest.fn(), - canScrollPrev: jest.fn( () => true ), - canScrollNext: jest.fn( () => true ), - selectedScrollSnap: jest.fn( () => 0 ), - scrollSnapList: jest.fn( () => [ 0, 0.5, 1 ] ), - ...overrides, -} ); - -describe( 'Carousel View Module', () => { - describe( 'Store Registration', () => { - it( 'should register store with correct namespace', () => { - // storeCall being defined proves store was called with the correct namespace - expect( storeCall ).toBeDefined(); - expect( storeConfig ).not.toBeNull(); - expect( storeCall[ 0 ] ).toBe( 'core-carousel/carousel' ); - } ); - - it( 'should register store with all required sections', () => { - expect( storeConfig ).toMatchObject( { - state: expect.any( Object ), - actions: expect.any( Object ), - callbacks: expect.any( Object ), - } ); - } ); - - it( 'should have state object defined with getters', () => { - expect( storeConfig?.state ).toBeDefined(); - expect( - Object.getOwnPropertyDescriptor( storeConfig.state, 'canScrollPrev' ) - ?.get, - ).toBeDefined(); - expect( - Object.getOwnPropertyDescriptor( storeConfig.state, 'canScrollNext' ) - ?.get, - ).toBeDefined(); - } ); - } ); - - describe( 'State Getters', () => { - beforeEach( () => { - jest.clearAllMocks(); - } ); - - describe( 'canScrollPrev', () => { - it( 'should return true when context.canScrollPrev is true', () => { - const mockContext = createMockContext( { canScrollPrev: true } ); - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = - Object.getOwnPropertyDescriptor( - storeConfig.state, - 'canScrollPrev', - )?.get?.() ?? false; - - expect( result ).toBe( true ); - } ); - - it( 'should return false when context.canScrollPrev is false', () => { - const mockContext = createMockContext( { canScrollPrev: false } ); - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = - Object.getOwnPropertyDescriptor( - storeConfig.state, - 'canScrollPrev', - )?.get?.() ?? true; - - expect( result ).toBe( false ); - } ); - } ); - - describe( 'canScrollNext', () => { - it( 'should return true when context.canScrollNext is true', () => { - const mockContext = createMockContext( { canScrollNext: true } ); - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = - Object.getOwnPropertyDescriptor( - storeConfig.state, - 'canScrollNext', - )?.get?.() ?? false; - - expect( result ).toBe( true ); - } ); - - it( 'should return false when context.canScrollNext is false', () => { - const mockContext = createMockContext( { canScrollNext: false } ); - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = - Object.getOwnPropertyDescriptor( - storeConfig.state, - 'canScrollNext', - )?.get?.() ?? true; - - expect( result ).toBe( false ); - } ); - } ); - } ); - - describe( 'Actions', () => { - beforeEach( () => { - jest.clearAllMocks(); - } ); - - describe( 'scrollPrev', () => { - it( 'should be defined as a function', () => { - expect( storeConfig?.actions?.scrollPrev ).toBeDefined(); - expect( typeof storeConfig?.actions?.scrollPrev ).toBe( 'function' ); - } ); - - it( 'should call embla.scrollPrev when embla instance exists', () => { - const { wrapper, viewport, button } = createMockCarouselDOM(); - const mockEmbla = createMockEmblaInstance(); - - // Set up embla instance on viewport using the helper - setEmblaOnViewport( viewport, mockEmbla ); - - ( getElement as jest.Mock ).mockReturnValue( { ref: button } ); - document.body.appendChild( wrapper ); - - storeConfig.actions.scrollPrev(); - - expect( mockEmbla.scrollPrev ).toHaveBeenCalledTimes( 1 ); - - document.body.removeChild( wrapper ); - } ); - - it( 'should log warning when embla instance not found', () => { - const consoleSpy = jest - .spyOn( console, 'warn' ) - .mockImplementation(); - const button = document.createElement( 'button' ); - - ( getElement as jest.Mock ).mockReturnValue( { ref: button } ); - - storeConfig.actions.scrollPrev(); - - expect( consoleSpy ).toHaveBeenCalledWith( - 'Carousel: Embla instance not found for scrollPrev', - ); - - consoleSpy.mockRestore(); - } ); - - it( 'should handle null element gracefully', () => { - const consoleSpy = jest - .spyOn( console, 'warn' ) - .mockImplementation(); - ( getElement as jest.Mock ).mockReturnValue( null ); - - expect( () => storeConfig.actions.scrollPrev() ).not.toThrow(); - expect( consoleSpy ).toHaveBeenCalled(); - - consoleSpy.mockRestore(); - } ); - } ); - - describe( 'scrollNext', () => { - it( 'should be defined as a function', () => { - expect( storeConfig?.actions?.scrollNext ).toBeDefined(); - expect( typeof storeConfig?.actions?.scrollNext ).toBe( 'function' ); - } ); - - it( 'should call embla.scrollNext when embla instance exists', () => { - const { wrapper, viewport, button } = createMockCarouselDOM(); - const mockEmbla = createMockEmblaInstance(); - - setEmblaOnViewport( viewport, mockEmbla ); - - ( getElement as jest.Mock ).mockReturnValue( { ref: button } ); - document.body.appendChild( wrapper ); - - storeConfig.actions.scrollNext(); - - expect( mockEmbla.scrollNext ).toHaveBeenCalledTimes( 1 ); - - document.body.removeChild( wrapper ); - } ); - - it( 'should log warning when embla instance not found', () => { - const consoleSpy = jest - .spyOn( console, 'warn' ) - .mockImplementation(); - const button = document.createElement( 'button' ); - - ( getElement as jest.Mock ).mockReturnValue( { ref: button } ); - - storeConfig.actions.scrollNext(); - - expect( consoleSpy ).toHaveBeenCalledWith( - 'Carousel: Embla instance not found for scrollNext', - ); - - consoleSpy.mockRestore(); - } ); - } ); - - describe( 'onDotClick', () => { - it( 'should be defined as a function', () => { - expect( storeConfig?.actions?.onDotClick ).toBeDefined(); - expect( typeof storeConfig?.actions?.onDotClick ).toBe( 'function' ); - } ); - - it( 'should call embla.scrollTo with correct index', () => { - const { wrapper, viewport, button } = createMockCarouselDOM(); - const mockEmbla = createMockEmblaInstance(); - - setEmblaOnViewport( viewport, mockEmbla ); - - const mockContext = createMockContext(); - ( mockContext as CarouselContext & { snap?: { index: number } } ).snap = - { index: 2 }; - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( { ref: button } ); - document.body.appendChild( wrapper ); - - storeConfig.actions.onDotClick(); - - expect( mockEmbla.scrollTo ).toHaveBeenCalledWith( 2 ); - - document.body.removeChild( wrapper ); - } ); - - it( 'should not throw when snap is undefined', () => { - const mockContext = createMockContext(); - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( null ); - - expect( () => storeConfig.actions.onDotClick() ).not.toThrow(); - } ); - - it( 'should handle snap.index of 0 correctly', () => { - const { wrapper, viewport, button } = createMockCarouselDOM(); - const mockEmbla = createMockEmblaInstance(); - - setEmblaOnViewport( viewport, mockEmbla ); - - const mockContext = createMockContext(); - ( mockContext as CarouselContext & { snap?: { index: number } } ).snap = - { index: 0 }; - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( { ref: button } ); - document.body.appendChild( wrapper ); - - storeConfig.actions.onDotClick(); - - expect( mockEmbla.scrollTo ).toHaveBeenCalledWith( 0 ); - - document.body.removeChild( wrapper ); - } ); - } ); - } ); - - describe( 'Callbacks', () => { - beforeEach( () => { - jest.clearAllMocks(); - } ); - - describe( 'isSlideActive', () => { - it( 'should be defined as a function', () => { - expect( storeConfig?.callbacks?.isSlideActive ).toBeDefined(); - expect( typeof storeConfig?.callbacks?.isSlideActive ).toBe( - 'function', - ); - } ); - - it( 'should return false when element is null', () => { - ( getElement as jest.Mock ).mockReturnValue( null ); - - const result = storeConfig.callbacks.isSlideActive(); - - expect( result ).toBe( false ); - } ); - - it( 'should return true when slide index matches selectedIndex', () => { - const container = document.createElement( 'div' ); - container.className = 'embla__container'; - - const slide1 = document.createElement( 'div' ); - slide1.className = 'embla__slide'; - const slide2 = document.createElement( 'div' ); - slide2.className = 'embla__slide'; - - container.appendChild( slide1 ); - container.appendChild( slide2 ); - - const mockContext = createMockContext( { selectedIndex: 1 } ); - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( { ref: slide2 } ); - - const result = storeConfig.callbacks.isSlideActive(); - - expect( result ).toBe( true ); - } ); - - it( 'should return false when slide index does not match selectedIndex', () => { - const container = document.createElement( 'div' ); - container.className = 'embla__container'; - - const slide1 = document.createElement( 'div' ); - slide1.className = 'embla__slide'; - const slide2 = document.createElement( 'div' ); - slide2.className = 'embla__slide'; - - container.appendChild( slide1 ); - container.appendChild( slide2 ); - - const mockContext = createMockContext( { selectedIndex: 0 } ); - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( { ref: slide2 } ); - - const result = storeConfig.callbacks.isSlideActive(); - - expect( result ).toBe( false ); - } ); - - it( 'should work with Query Loop posts (.wp-block-post)', () => { - const container = document.createElement( 'div' ); - - const post1 = document.createElement( 'li' ); - post1.className = 'wp-block-post'; - const post2 = document.createElement( 'li' ); - post2.className = 'wp-block-post'; - - container.appendChild( post1 ); - container.appendChild( post2 ); - - const mockContext = createMockContext( { selectedIndex: 0 } ); - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( { ref: post1 } ); - - const result = storeConfig.callbacks.isSlideActive(); - - expect( result ).toBe( true ); - } ); - } ); - - describe( 'isDotActive', () => { - it( 'should be defined as a function', () => { - expect( storeConfig?.callbacks?.isDotActive ).toBeDefined(); - expect( typeof storeConfig?.callbacks?.isDotActive ).toBe( 'function' ); - } ); - - it( 'should return true when snap.index matches selectedIndex', () => { - const mockContext = createMockContext( { selectedIndex: 2 } ); - ( mockContext as CarouselContext & { snap?: { index: number } } ).snap = - { index: 2 }; - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = storeConfig.callbacks.isDotActive(); - - expect( result ).toBe( true ); - } ); - - it( 'should return false when snap.index does not match selectedIndex', () => { - const mockContext = createMockContext( { selectedIndex: 0 } ); - ( mockContext as CarouselContext & { snap?: { index: number } } ).snap = - { index: 2 }; - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = storeConfig.callbacks.isDotActive(); - - expect( result ).toBe( false ); - } ); - } ); - - describe( 'getDotLabel', () => { - it( 'should be defined as a function', () => { - expect( storeConfig?.callbacks?.getDotLabel ).toBeDefined(); - expect( typeof storeConfig?.callbacks?.getDotLabel ).toBe( 'function' ); - } ); - - it( 'should return formatted label with correct index (1-based)', () => { - const mockContext = createMockContext( { - ariaLabelPattern: 'Go to slide %d', - } ); - ( mockContext as CarouselContext & { snap?: { index: number } } ).snap = - { index: 2 }; - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = storeConfig.callbacks.getDotLabel(); - - expect( result ).toBe( 'Go to slide 3' ); - } ); - - it( 'should handle first slide (index 0) correctly', () => { - const mockContext = createMockContext( { - ariaLabelPattern: 'Slide %d of 5', - } ); - ( mockContext as CarouselContext & { snap?: { index: number } } ).snap = - { index: 0 }; - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = storeConfig.callbacks.getDotLabel(); - - expect( result ).toBe( 'Slide 1 of 5' ); - } ); - - it( 'should handle undefined snap index', () => { - const mockContext = createMockContext( { - ariaLabelPattern: 'Go to slide %d', - } ); - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - const result = storeConfig.callbacks.getDotLabel(); - - expect( result ).toBe( 'Go to slide 1' ); - } ); - } ); - - describe( 'initCarousel', () => { - it( 'should be defined as a function', () => { - expect( storeConfig?.callbacks?.initCarousel ).toBeDefined(); - expect( typeof storeConfig?.callbacks?.initCarousel ).toBe( - 'function', - ); - } ); - - it( 'should return early and log warning for invalid element', () => { - const consoleSpy = jest - .spyOn( console, 'warn' ) - .mockImplementation(); - const mockContext = createMockContext(); - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( null ); - - const result = storeConfig.callbacks.initCarousel(); - - expect( consoleSpy ).toHaveBeenCalledWith( - 'Carousel: Invalid root element', - null, - ); - expect( result ).toBeUndefined(); - - consoleSpy.mockRestore(); - } ); - - it( 'should log warning when viewport not found', () => { - const consoleSpy = jest - .spyOn( console, 'warn' ) - .mockImplementation(); - const mockContext = createMockContext(); - const element = document.createElement( 'div' ); - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( { ref: element } ); - - const result = storeConfig.callbacks.initCarousel(); - - expect( consoleSpy ).toHaveBeenCalledWith( - 'Carousel: Viewport (.embla) not found', - ); - expect( result ).toBeUndefined(); - - consoleSpy.mockRestore(); - } ); - - it( 'should handle errors gracefully and log them', () => { - const consoleErrorSpy = jest - .spyOn( console, 'error' ) - .mockImplementation(); - const mockContext = createMockContext(); - - // Create element that will cause an error - const element = { - querySelector: () => { - throw new Error( 'Test error' ); - }, - }; - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( { ref: element } ); - - const result = storeConfig.callbacks.initCarousel(); - - expect( consoleErrorSpy ).toHaveBeenCalledWith( - 'Carousel: Error in initCarousel', - expect.any( Error ), - ); - expect( result ).toBeNull(); - - consoleErrorSpy.mockRestore(); - } ); - } ); - } ); -} ); - -describe( 'Embla Carousel Integration', () => { - // Type-safe helper to get mocked Embla instance - const getMockedEmblaCarousel = () => - EmblaCarousel as unknown as jest.Mock; - - it( 'should have EmblaCarousel mocked', () => { - expect( EmblaCarousel ).toBeDefined(); - expect( jest.isMockFunction( EmblaCarousel ) ).toBe( true ); - } ); - - it( 'should create embla instance with correct methods', () => { - const mockInstance = getMockedEmblaCarousel()(); - - expect( mockInstance.scrollPrev ).toBeDefined(); - expect( mockInstance.scrollNext ).toBeDefined(); - expect( mockInstance.scrollTo ).toBeDefined(); - expect( mockInstance.on ).toBeDefined(); - expect( mockInstance.destroy ).toBeDefined(); - } ); - - it( 'should have scrollPrev as a callable function', () => { - const mockInstance = getMockedEmblaCarousel()(); - - expect( () => mockInstance.scrollPrev() ).not.toThrow(); - } ); - - it( 'should have scrollNext as a callable function', () => { - const mockInstance = getMockedEmblaCarousel()(); - - expect( () => mockInstance.scrollNext() ).not.toThrow(); - } ); - - it( 'should have scrollTo as a callable function', () => { - const mockInstance = getMockedEmblaCarousel()(); - - expect( () => mockInstance.scrollTo( 2 ) ).not.toThrow(); - } ); - - it( 'should have on method for event listeners', () => { - const mockInstance = getMockedEmblaCarousel()(); - - expect( () => mockInstance.on( 'select', jest.fn() ) ).not.toThrow(); - } ); - - it( 'should have destroy method for cleanup', () => { - const mockInstance = getMockedEmblaCarousel()(); - - expect( () => mockInstance.destroy() ).not.toThrow(); - } ); -} ); - -describe( 'Element Reference Handling', () => { - describe( 'getElement variations', () => { - beforeEach( () => { - jest.clearAllMocks(); - } ); - - it( 'should handle getElement returning HTMLElement directly', () => { - const consoleSpy = jest.spyOn( console, 'warn' ).mockImplementation(); - const element = document.createElement( 'div' ); - - ( getElement as jest.Mock ).mockReturnValue( element ); - - // This should not throw - expect( () => storeConfig.actions.scrollPrev() ).not.toThrow(); - - consoleSpy.mockRestore(); - } ); - - it( 'should handle getElement returning object with ref', () => { - const consoleSpy = jest.spyOn( console, 'warn' ).mockImplementation(); - const element = document.createElement( 'div' ); - - ( getElement as jest.Mock ).mockReturnValue( { ref: element } ); - - expect( () => storeConfig.actions.scrollPrev() ).not.toThrow(); - - consoleSpy.mockRestore(); - } ); - - it( 'should handle getElement returning object with null ref', () => { - const consoleSpy = jest.spyOn( console, 'warn' ).mockImplementation(); - - ( getElement as jest.Mock ).mockReturnValue( { ref: null } ); - - expect( () => storeConfig.actions.scrollPrev() ).not.toThrow(); - - consoleSpy.mockRestore(); - } ); - - it( 'should handle getElement returning undefined', () => { - const consoleSpy = jest.spyOn( console, 'warn' ).mockImplementation(); - - ( getElement as jest.Mock ).mockReturnValue( undefined ); - - expect( () => storeConfig.actions.scrollPrev() ).not.toThrow(); - - consoleSpy.mockRestore(); - } ); - } ); -} ); - -describe( 'Edge Cases and Error Handling', () => { - beforeEach( () => { - jest.clearAllMocks(); - } ); - - it( 'should handle carousel with no slides gracefully', () => { - const container = document.createElement( 'div' ); - container.className = 'embla__container'; - - const mockContext = createMockContext( { - selectedIndex: 0, - scrollSnaps: [], - } ); - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - ( getElement as jest.Mock ).mockReturnValue( { - ref: container, - } ); - - // Should not throw - expect( () => storeConfig.callbacks.isSlideActive() ).not.toThrow(); - } ); - - it( 'should handle RTL direction in context', () => { - const mockContext = createMockContext( { - options: { direction: 'rtl', loop: true }, - } ); - - ( getContext as jest.Mock ).mockReturnValue( mockContext ); - - expect( mockContext.options.direction ).toBe( 'rtl' ); - } ); - - it( 'should handle autoplay configuration', () => { - const mockContextWithAutoplay = createMockContext( { - autoplay: { - delay: 3000, - stopOnInteraction: true, - stopOnMouseEnter: false, - }, - isPlaying: true, - } ); - - expect( mockContextWithAutoplay.autoplay ).toEqual( { - delay: 3000, - stopOnInteraction: true, - stopOnMouseEnter: false, - } ); - expect( mockContextWithAutoplay.isPlaying ).toBe( true ); - } ); - - it( 'should handle timerIterationId for animation resets', () => { - const mockContext = createMockContext( { - timerIterationId: 5, - } ); - - expect( mockContext.timerIterationId ).toBe( 5 ); - - // Simulate increment on slide change - mockContext.timerIterationId += 1; - - expect( mockContext.timerIterationId ).toBe( 6 ); - } ); - - it( 'should handle large number of slides', () => { - const scrollSnaps = Array.from( { length: 100 }, ( _, i ) => ( { - index: i, - } ) ); - const mockContext = createMockContext( { - scrollSnaps, - selectedIndex: 50, - } ); - - expect( mockContext.scrollSnaps ).toHaveLength( 100 ); - expect( mockContext.selectedIndex ).toBe( 50 ); - } ); -} ); diff --git a/tests/js/__mocks__/wordpress-interactivity.ts b/tests/js/__mocks__/wordpress-interactivity.ts deleted file mode 100644 index 460b66d..0000000 --- a/tests/js/__mocks__/wordpress-interactivity.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Mock for @wordpress/interactivity module. - */ - -export const store = jest.fn( ( _namespace: string, config: unknown ) => config ); -export const getContext = jest.fn( () => ( {} ) ); -export const getElement = jest.fn( () => ( { ref: null } ) ); -export const withScope = jest.fn( ( callback: () => void ) => callback ); diff --git a/tests/js/setup.ts b/tests/js/setup.ts deleted file mode 100644 index a95a3c0..0000000 --- a/tests/js/setup.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Jest setup file for Core Carousel tests. - * - * This file runs before each test file and sets up global mocks - * for WordPress and Embla Carousel dependencies. - */ - -import '@testing-library/jest-dom'; - -/** - * Mock embla-carousel module. - */ -jest.mock( 'embla-carousel', () => ( { - __esModule: true, - default: jest.fn( () => ( { - canScrollPrev: jest.fn( () => true ), - canScrollNext: jest.fn( () => true ), - scrollPrev: jest.fn(), - scrollNext: jest.fn(), - scrollTo: jest.fn(), - selectedScrollSnap: jest.fn( () => 0 ), - scrollSnapList: jest.fn( () => [ 0, 1, 2 ] ), - slideNodes: jest.fn( () => [] ), - on: jest.fn(), - off: jest.fn(), - destroy: jest.fn(), - reInit: jest.fn(), - rootNode: jest.fn(), - containerNode: jest.fn(), - plugins: jest.fn( () => ( {} ) ), - } ) ), -} ) ); - -/** - * Mock embla-carousel-autoplay module. - */ -jest.mock( 'embla-carousel-autoplay', () => ( { - __esModule: true, - default: jest.fn( () => ( { - name: 'autoplay', - options: { delay: 3000 }, - init: jest.fn(), - destroy: jest.fn(), - play: jest.fn(), - stop: jest.fn(), - reset: jest.fn(), - isPlaying: jest.fn( () => false ), - } ) ), -} ) ); - -/** - * Mock WordPress block editor components. - */ -jest.mock( '@wordpress/block-editor', () => ( { - useBlockProps: jest.fn( ( props = {} ) => ( { - className: 'wp-block', - ...props, - } ) ), - useInnerBlocksProps: jest.fn( ( blockProps = {} ) => ( { - ...blockProps, - children: null, - } ) ), - InspectorControls: jest.fn( ( { children } ) => children ), - BlockControls: jest.fn( ( { children } ) => children ), - InnerBlocks: { - Content: jest.fn( () => null ), - }, - store: { - name: 'core/block-editor', - }, -} ) ); - -/** - * Mock WordPress components. - */ -jest.mock( '@wordpress/components', () => ( { - PanelBody: jest.fn( ( { children } ) => children ), - ToggleControl: jest.fn( () => null ), - RangeControl: jest.fn( () => null ), - SelectControl: jest.fn( () => null ), - Button: jest.fn( ( { children } ) => children ), - Flex: jest.fn( ( { children } ) => children ), - FlexItem: jest.fn( ( { children } ) => children ), - FlexBlock: jest.fn( ( { children } ) => children ), - __experimentalUnitControl: jest.fn( () => null ), -} ) ); - -/** - * Mock WordPress data module. - */ -jest.mock( '@wordpress/data', () => ( { - useSelect: jest.fn( () => ( {} ) ), - useDispatch: jest.fn( () => ( {} ) ), - select: jest.fn( () => ( {} ) ), - dispatch: jest.fn( () => ( {} ) ), - subscribe: jest.fn(), - createReduxStore: jest.fn(), - register: jest.fn(), -} ) ); - -/** - * Mock WordPress i18n module. - */ -jest.mock( '@wordpress/i18n', () => ( { - __: jest.fn( ( text: string ) => text ), - _x: jest.fn( ( text: string ) => text ), - _n: jest.fn( ( single: string ) => single ), - sprintf: jest.fn( ( format: string, ...args: unknown[] ) => { - let result = format; - args.forEach( ( arg ) => { - result = result.replace( '%s', String( arg ) ); - result = result.replace( '%d', String( arg ) ); - } ); - return result; - } ), -} ) ); - -/** - * Mock WordPress element module. - */ -jest.mock( '@wordpress/element', () => { - const actualReact = jest.requireActual( 'react' ); - return { - ...actualReact, - createInterpolateElement: jest.fn( ( text: string ) => text ), - RawHTML: jest.fn( ( { children } ) => children ), - }; -} ); - -/** - * Helper to reset all mocks between tests. - */ -beforeEach( () => { - jest.clearAllMocks(); -} ); - -/** - * Helper factory to create mock Embla instance for use in tests. - */ -export const createMockEmblaInstance = () => ( { - canScrollPrev: jest.fn( () => true ), - canScrollNext: jest.fn( () => true ), - scrollPrev: jest.fn(), - scrollNext: jest.fn(), - scrollTo: jest.fn(), - selectedScrollSnap: jest.fn( () => 0 ), - scrollSnapList: jest.fn( () => [ 0, 1, 2 ] ), - slideNodes: jest.fn( () => [] ), - on: jest.fn(), - off: jest.fn(), - destroy: jest.fn(), - reInit: jest.fn(), - rootNode: jest.fn( () => document.createElement( 'div' ) ), - containerNode: jest.fn( () => document.createElement( 'div' ) ), - plugins: jest.fn( () => ( {} ) ), -} ); diff --git a/tests/js/tsconfig.json b/tests/js/tsconfig.json deleted file mode 100644 index 169d5dd..0000000 --- a/tests/js/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "../_output/js", - "noEmit": true, - "types": ["jest", "node"] - }, - "include": ["./**/*.ts", "./**/*.tsx"] -} diff --git a/tests/php/Unit/PluginTest.php b/tests/php/Unit/PluginTest.php deleted file mode 100644 index 7d60751..0000000 --- a/tests/php/Unit/PluginTest.php +++ /dev/null @@ -1,410 +0,0 @@ - - */ - private const EXPECTED_BLOCKS = [ - 'carousel', - 'carousel/controls', - 'carousel/dots', - 'carousel/viewport', - 'carousel/slide', - ]; - - /** - * Helper to get Plugin instance via reflection without triggering singleton. - * - * @return Plugin - */ - private function getPluginInstance(): Plugin { - $reflection = new \ReflectionClass( Plugin::class ); - return $reflection->newInstanceWithoutConstructor(); - } - - /** - * Helper to invoke a protected/private method on an object. - * - * @param object $object The object instance. - * @param string $methodName The method name to invoke. - * @param array $args Arguments to pass to the method. - * @return mixed The return value of the method. - */ - private function invokeMethod( object $object, string $methodName, array $args = [] ): mixed { - $reflection = new \ReflectionClass( $object ); - $method = $reflection->getMethod( $methodName ); - - return $method->invokeArgs( $object, $args ); - } - - /** - * Test that register_block_category adds the category. - * - * @return void - */ - public function test_register_block_category_adds_category(): void { - Functions\when( '__' )->returnArg(); - - $instance = $this->getPluginInstance(); - - $existing_categories = [ - [ - 'slug' => 'text', - 'title' => 'Text', - ], - ]; - - $result = $this->invokeMethod( $instance, 'register_block_category', [ $existing_categories ] ); - - $this->assertCount( 2, $result ); - $this->assertSame( 'core-carousel', $result[1]['slug'] ); - $this->assertSame( 'Core Carousel', $result[1]['title'] ); - } - - /** - * Test that register_block_category preserves existing categories. - * - * @return void - */ - public function test_register_block_category_preserves_existing(): void { - Functions\when( '__' )->returnArg(); - - $instance = $this->getPluginInstance(); - - $existing_categories = [ - [ - 'slug' => 'media', - 'title' => 'Media', - ], - [ - 'slug' => 'design', - 'title' => 'Design', - ], - ]; - - $result = $this->invokeMethod( $instance, 'register_block_category', [ $existing_categories ] ); - - $this->assertCount( 3, $result ); - $this->assertSame( 'media', $result[0]['slug'] ); - $this->assertSame( 'design', $result[1]['slug'] ); - $this->assertSame( 'core-carousel', $result[2]['slug'] ); - } - - /** - * Test that category is added to empty categories array. - * - * @return void - */ - public function test_register_block_category_with_empty_array(): void { - Functions\when( '__' )->returnArg(); - - $instance = $this->getPluginInstance(); - $result = $this->invokeMethod( $instance, 'register_block_category', [ [] ] ); - - $this->assertCount( 1, $result ); - $this->assertSame( 'core-carousel', $result[0]['slug'] ); - } - - /** - * Test that register_blocks registers all expected blocks. - * - * @return void - */ - public function test_register_blocks_registers_all_blocks(): void { - $registered_blocks = []; - - Functions\when( 'register_block_type' )->alias( - function ( string $path ) use ( &$registered_blocks ): void { - $registered_blocks[] = $path; - } - ); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_blocks' ); - - $this->assertCount( 5, $registered_blocks ); - - // Verify each expected block is registered - foreach ( self::EXPECTED_BLOCKS as $block ) { - $found = false; - foreach ( $registered_blocks as $path ) { - if ( str_contains( $path, "/blocks/{$block}" ) ) { - $found = true; - break; - } - } - $this->assertTrue( $found, "Block '{$block}' should be registered." ); - } - } - - /** - * Test that blocks are registered in the correct order. - * - * @return void - */ - public function test_register_blocks_in_correct_order(): void { - $registered_blocks = []; - - Functions\when( 'register_block_type' )->alias( - function ( string $path ) use ( &$registered_blocks ): void { - $registered_blocks[] = $path; - } - ); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_blocks' ); - - $this->assertStringContainsString( '/blocks/carousel', $registered_blocks[0] ); - $this->assertStringContainsString( '/blocks/carousel/controls', $registered_blocks[1] ); - $this->assertStringContainsString( '/blocks/carousel/dots', $registered_blocks[2] ); - $this->assertStringContainsString( '/blocks/carousel/viewport', $registered_blocks[3] ); - $this->assertStringContainsString( '/blocks/carousel/slide', $registered_blocks[4] ); - } - - /** - * Test that register_blocks does nothing when build path is not defined. - * - * @return void - */ - public function test_register_blocks_handles_missing_build_path(): void { - // The actual behavior check: register_block_type should be called - // for each block when the constant is defined (as it is in our tests). - Functions\expect( 'register_block_type' )->times( 5 ); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_blocks' ); - - // Assert that we got here without errors - $this->assertTrue( true ); - } - - /** - * Test that register_pattern_category registers the category. - * - * @return void - */ - public function test_register_pattern_category_registers_category(): void { - $category_registered = false; - - Functions\when( '__' )->returnArg(); - Functions\expect( 'register_block_pattern_category' ) - ->once() - ->with( - 'core-carousel', - \Mockery::type( 'array' ) - ) - ->andReturnUsing( - function () use ( &$category_registered ): void { - $category_registered = true; - } - ); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_pattern_category' ); - - $this->assertTrue( $category_registered ); - } - - /** - * Test that pattern category includes proper label. - * - * @return void - */ - public function test_register_pattern_category_includes_label(): void { - Functions\when( '__' )->returnArg(); - - /** @var array|null $captured_args */ - $captured_args = null; - - Functions\expect( 'register_block_pattern_category' ) - ->once() - ->with( - 'core-carousel', - \Mockery::on( - function ( $args ) use ( &$captured_args ): bool { - $captured_args = $args; - return true; - } - ) - ); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_pattern_category' ); - - $this->assertIsArray( $captured_args ); - $this->assertNotNull( $captured_args ); - $this->assertArrayHasKey( 'label', $captured_args ); - $this->assertSame( 'Core Carousel', $captured_args['label'] ); - } - - /** - * Test register_block_patterns uses cached patterns when available. - * - * @return void - */ - public function test_register_block_patterns_uses_cache(): void { - $cached_patterns = [ - [ - 'slug' => 'core-carousel/test-pattern', - 'args' => [ - 'title' => 'Test Pattern', - 'content' => '

Test

', - ], - ], - ]; - - $pattern_registered = false; - - Functions\when( '__' )->returnArg(); - Functions\expect( 'get_transient' ) - ->once() - ->with( 'core_carousel_patterns_cache' ) - ->andReturn( $cached_patterns ); - - Functions\expect( 'register_block_pattern' ) - ->once() - ->with( 'core-carousel/test-pattern', \Mockery::type( 'array' ) ) - ->andReturnUsing( - function () use ( &$pattern_registered ): void { - $pattern_registered = true; - } - ); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_block_patterns' ); - - $this->assertTrue( $pattern_registered ); - } - - /** - * Test register_block_patterns handles empty patterns gracefully. - * - * @return void - */ - public function test_register_block_patterns_handles_empty(): void { - Functions\expect( 'get_transient' ) - ->once() - ->with( 'core_carousel_patterns_cache' ) - ->andReturn( [] ); - - Functions\expect( 'register_block_pattern' )->never(); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_block_patterns' ); - - // Assert method completed without registering patterns - $this->assertTrue( true ); - } - - /** - * Test register_block_patterns registers multiple patterns. - * - * @return void - */ - public function test_register_block_patterns_registers_multiple(): void { - $cached_patterns = [ - [ - 'slug' => 'core-carousel/pattern-one', - 'args' => [ - 'title' => 'Pattern One', - 'content' => '

One

', - ], - ], - [ - 'slug' => 'core-carousel/pattern-two', - 'args' => [ - 'title' => 'Pattern Two', - 'content' => '

Two

', - ], - ], - [ - 'slug' => 'core-carousel/pattern-three', - 'args' => [ - 'title' => 'Pattern Three', - 'content' => '

Three

', - ], - ], - ]; - - $registered_patterns = []; - - Functions\when( '__' )->returnArg(); - Functions\expect( 'get_transient' ) - ->once() - ->andReturn( $cached_patterns ); - - Functions\expect( 'register_block_pattern' ) - ->times( 3 ) - ->andReturnUsing( - function ( $slug ) use ( &$registered_patterns ): void { - $registered_patterns[] = $slug; - } - ); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_block_patterns' ); - - $this->assertCount( 3, $registered_patterns ); - $this->assertContains( 'core-carousel/pattern-one', $registered_patterns ); - $this->assertContains( 'core-carousel/pattern-two', $registered_patterns ); - $this->assertContains( 'core-carousel/pattern-three', $registered_patterns ); - } - - /** - * Test that patterns without required fields are handled. - * - * @return void - */ - public function test_register_block_patterns_handles_invalid_structure(): void { - // Pattern missing 'args' key - $cached_patterns = [ - [ - 'slug' => 'core-carousel/valid-pattern', - 'args' => [ - 'title' => 'Valid', - 'content' => '

Valid

', - ], - ], - ]; - - Functions\when( '__' )->returnArg(); - Functions\expect( 'get_transient' ) - ->once() - ->andReturn( $cached_patterns ); - - Functions\expect( 'register_block_pattern' )->once(); - - $instance = $this->getPluginInstance(); - $this->invokeMethod( $instance, 'register_block_patterns' ); - - // Assert completed successfully - $this->assertTrue( true ); - } -} diff --git a/tests/php/Unit/Traits/SingletonTest.php b/tests/php/Unit/Traits/SingletonTest.php deleted file mode 100644 index 92511a6..0000000 --- a/tests/php/Unit/Traits/SingletonTest.php +++ /dev/null @@ -1,92 +0,0 @@ -constructor_called = true; - } -} - -/** - * Test class B for singleton tests. - */ -class SingletonTestClassB { - use Singleton; -} - -/** - * Test class C for singleton tests. - */ -class SingletonTestClassC { - use Singleton; - - public bool $constructor_called = false; - - protected function __construct() { - $this->constructor_called = true; - } -} - -/** - * Tests for the Singleton trait. - */ -class SingletonTest extends UnitTestCase { - /** - * Test that get_instance returns an instance of the class. - * - * @return void - */ - public function test_get_instance_returns_instance(): void { - Actions\expectDone( 'core_carousel_singleton_init_' . SingletonTestClassA::class )->once(); - - $instance = SingletonTestClassA::get_instance(); - - $this->assertInstanceOf( SingletonTestClassA::class, $instance ); - } - - /** - * Test that get_instance returns the same instance on subsequent calls. - * - * @return void - */ - public function test_get_instance_returns_same_instance(): void { - Actions\expectDone( 'core_carousel_singleton_init_' . SingletonTestClassB::class )->once(); - - $instance1 = SingletonTestClassB::get_instance(); - $instance2 = SingletonTestClassB::get_instance(); - - $this->assertSame( $instance1, $instance2 ); - } - - /** - * Test that constructor is called on first instantiation. - * - * @return void - */ - public function test_constructor_is_called(): void { - Actions\expectDone( 'core_carousel_singleton_init_' . SingletonTestClassC::class )->once(); - - $instance = SingletonTestClassC::get_instance(); - - $this->assertTrue( $instance->constructor_called ); - } -} diff --git a/tests/php/Unit/UnitTestCase.php b/tests/php/Unit/UnitTestCase.php deleted file mode 100644 index da71133..0000000 --- a/tests/php/Unit/UnitTestCase.php +++ /dev/null @@ -1,38 +0,0 @@ -