From 0298bb34fa664b665925760db06a0bf85b4f3e33 Mon Sep 17 00:00:00 2001 From: Juliette <663378+jrfnl@users.noreply.github.com> Date: Wed, 8 Jan 2025 17:23:59 +0100 Subject: [PATCH] PHPUnit 11.5.0 | AssertContainsOnly trait: polyfill the Assert::assertContains[Not]Only*() methods (#225) PHPUnit 11.5.0 introduced a range of new assertions. These assertions are specialized alternatives to the pre-existing `assert[Not]ContainsOnly()` methods, which are now soft deprecated and will be removed in PHPUnit 13.0. This commit: * Adds two traits with the same name. One to polyfill the methods when not available in PHPUnit. The other to allow for `use`-ing the trait in PHPUnit versions in which the methods are already natively available. * Adds logic to the custom autoloader which will load the correct trait depending on the PHPUnit version used. * Adds tests. Most polyfilled methods can just fall-through to the pre-existing methods as a polyfill. The exceptions to this rule are: * `assertContains[Not]OnlyIterable()` which needs custom logic for PHPUnit < 7.1.0 in which the PHP native `iterable` type was not yet supported. * `assertContains[Not]OnlyClosedResource()` which needs custom logic for PHP < 7.2 in which the PHP native `resource (closed)` type did not exist yet. In this last case, the custom logic is used for the polyfill on all PHP versions as there is no functional check (in contrast to a version check) which can be used to determine whether the `resource (closed)` type is available. All new methods are loosely tested. Includes: * Adding information on the new polyfill to the README. * Adding the new polyfill to the existing `TestCases` classes. Refs: * https://github.com/sebastianbergmann/phpunit/commit/a726e0396e71cc77bc0b459f93481c29e726dbd8 Fixes 214 --- README.md | 54 + phpstan.neon.dist | 1 + phpunitpolyfills-autoload.php | 21 + src/Polyfills/AssertContainsOnly.php | 472 ++++++++ src/Polyfills/AssertContainsOnly_Empty.php | 10 + src/TestCases/TestCasePHPUnitGte8.php | 2 + src/TestCases/TestCasePHPUnitLte7.php | 2 + src/TestCases/XTestCase.php | 2 + tests/Polyfills/AssertContainsOnlyTest.php | 1243 ++++++++++++++++++++ tests/TestCases/TestCaseTestTrait.php | 9 + 10 files changed, 1816 insertions(+) create mode 100644 src/Polyfills/AssertContainsOnly.php create mode 100644 src/Polyfills/AssertContainsOnly_Empty.php create mode 100644 tests/Polyfills/AssertContainsOnlyTest.php diff --git a/README.md b/README.md index b80d4ed..44018c9 100644 --- a/README.md +++ b/README.md @@ -499,6 +499,60 @@ The `assertObjectNotEquals()` assertion was introduced in PHPUnit 11.2.0. [`Assert::assertObjectNotEquals()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertobjectequals +#### PHPUnit < 11.5.0: `Yoast\PHPUnitPolyfills\Polyfills\AssertContainsOnly` + +Polyfills the following methods: + +| | | +| ------------------------------------------------ | --------------------------------------------------- | +| [`Assert::assertContainsOnlyArray()`] | [`Assert::assertContainsNotOnlyArray()`] | +| [`Assert::assertContainsOnlyBool()`] | [`Assert::assertContainsNotOnlyBool()`] | +| [`Assert::assertContainsOnlyCallable()`] | [`Assert::assertContainsNotOnlyCallable()`] | +| [`Assert::assertContainsOnlyFloat()`] | [`Assert::assertContainsNotOnlyFloat()`] | +| [`Assert::assertContainsOnlyInt()`] | [`Assert::assertContainsNotOnlyInt()`] | +| [`Assert::assertContainsOnlyIterable()`] | [`Assert::assertContainsNotOnlyIterable()`] | +| [`Assert::assertContainsOnlyNull()`] | [`Assert::assertContainsNotOnlyNull()`] | +| [`Assert::assertContainsOnlyNumeric()`] | [`Assert::assertContainsNotOnlyNumeric()`] | +| [`Assert::assertContainsOnlyObject()`] | [`Assert::assertContainsNotOnlyObject()`] | +| [`Assert::assertContainsOnlyResource()`] | [`Assert::assertContainsNotOnlyResource()`] | +| [`Assert::assertContainsOnlyClosedResource()`] * | [`Assert::assertContainsNotOnlyClosedResource()`] * | +| [`Assert::assertContainsOnlyScalar()`] | [`Assert::assertContainsNotOnlyScalar()`] | +| [`Assert::assertContainsOnlyString()`] | [`Assert::assertContainsNotOnlyString()`] | +| | [`Assert::assertContainsNotOnlyInstancesOf()`] | + + +These methods were introduced in PHPUnit 11.5.0 as alternatives to the `Assert::assertContainsOnly()` and `Assert::assertNotContainsOnly()` methods, which were soft deprecated in PHPUnit 11.5.0, hard deprecated (warning) in PHPUnit 12.0.0 and will be removed in PHPUnit 13.0.0. + +* The `assertContains[Not]OnlyClosedResource()` methods are affected by issues in older PHP versions. Please read the [warning about checking for closed resources and how to optional skip such tests](https://github.com/Yoast/PHPUnit-Polyfills/tree/1.x?tab=readme-ov-file#phpunit--930-yoastphpunitpolyfillspolyfillsassertclosedresource). + +[`Assert::assertContainsOnlyArray()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyarray +[`Assert::assertContainsNotOnlyArray()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyarray +[`Assert::assertContainsOnlyBool()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlybool +[`Assert::assertContainsNotOnlyBool()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlybool +[`Assert::assertContainsOnlyCallable()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlycallable +[`Assert::assertContainsNotOnlyCallable()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlycallable +[`Assert::assertContainsOnlyFloat()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyfloat +[`Assert::assertContainsNotOnlyFloat()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyfloat +[`Assert::assertContainsOnlyInt()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyint +[`Assert::assertContainsNotOnlyInt()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyint +[`Assert::assertContainsOnlyIterable()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyiterable +[`Assert::assertContainsNotOnlyIterable()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyiterable +[`Assert::assertContainsOnlyNull()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlynull +[`Assert::assertContainsNotOnlyNull()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlynull +[`Assert::assertContainsOnlyNumeric()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlynumeric +[`Assert::assertContainsNotOnlyNumeric()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlynumeric +[`Assert::assertContainsOnlyObject()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyobject +[`Assert::assertContainsNotOnlyObject()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyobject +[`Assert::assertContainsOnlyResource()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyresource +[`Assert::assertContainsNotOnlyResource()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyresource +[`Assert::assertContainsOnlyClosedResource()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyclosedresource +[`Assert::assertContainsNotOnlyClosedResource()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyclosedresource +[`Assert::assertContainsOnlyScalar()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyscalar +[`Assert::assertContainsNotOnlyScalar()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyscalar +[`Assert::assertContainsOnlyString()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlystring +[`Assert::assertContainsNotOnlyString()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlystring +[`Assert::assertContainsNotOnlyInstancesOf()`]: https://docs.phpunit.de/en/11.5/assertions.html#assertcontainsonlyinstancesof + ### TestCases diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 5e02295..20b9dea 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -15,6 +15,7 @@ parameters: - src/TestCases/TestCasePHPUnitLte7.php # Triggers "Referencing prefixed PHPUnit class: PHPUnitPHAR\SebastianBergmann\Exporter\Exporter." notices, which cannot be ignored. - src/Polyfills/AssertClosedResource.php + - src/Polyfills/AssertContainsOnly.php - src/Polyfills/AssertIgnoringLineEndings.php treatPhpDocTypesAsCertain: false diff --git a/phpunitpolyfills-autoload.php b/phpunitpolyfills-autoload.php index 265bb61..e8a45ee 100644 --- a/phpunitpolyfills-autoload.php +++ b/phpunitpolyfills-autoload.php @@ -98,6 +98,10 @@ public static function load( $className ) { self::loadAssertObjectNotEquals(); return true; + case 'Yoast\PHPUnitPolyfills\Polyfills\AssertContainsOnly': + self::loadAssertContainsOnly(); + return true; + case 'Yoast\PHPUnitPolyfills\TestCases\TestCase': self::loadTestCase(); return true; @@ -381,6 +385,23 @@ public static function loadAssertObjectNotEquals() { require_once __DIR__ . '/src/Polyfills/AssertObjectNotEquals_Empty.php'; } + /** + * Load the AssertContainsOnly polyfill or an empty trait with the same name + * if a PHPUnit version is used which already contains this functionality. + * + * @return void + */ + public static function loadAssertContainsOnly() { + if ( \method_exists( Assert::class, 'assertContainsOnlyIterable' ) === false ) { + // PHPUnit < 11.5.0. + require_once __DIR__ . '/src/Polyfills/AssertContainsOnly.php'; + return; + } + + // PHPUnit >= 11.5.0. + require_once __DIR__ . '/src/Polyfills/AssertContainsOnly_Empty.php'; + } + /** * Load the appropriate TestCase class based on the PHPUnit version being used. * diff --git a/src/Polyfills/AssertContainsOnly.php b/src/Polyfills/AssertContainsOnly.php new file mode 100644 index 0000000..a05a1c4 --- /dev/null +++ b/src/Polyfills/AssertContainsOnly.php @@ -0,0 +1,472 @@ + $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyInstancesOf( string $type, $haystack, string $message = '' ) { + static::assertNotContainsOnly( $type, $haystack, false, $message ); + } + + /** + * Asserts that $haystack only contains values of type array. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyArray( $haystack, string $message = '' ) { + static::assertContainsOnly( 'array', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type array. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyArray( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'array', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type boolean. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyBool( $haystack, string $message = '' ) { + static::assertContainsOnly( 'bool', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type boolean. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyBool( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'bool', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type callable. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyCallable( $haystack, string $message = '' ) { + static::assertContainsOnly( 'callable', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type callable. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyCallable( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'callable', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type float. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyFloat( $haystack, string $message = '' ) { + static::assertContainsOnly( 'float', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type float. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyFloat( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'float', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type integer. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyInt( $haystack, string $message = '' ) { + static::assertContainsOnly( 'int', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type integer. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyInt( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'int', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type iterable. + * + * {@internal Support for `iterable` was only added to the `IsType` constraint + * in PHPUnit 7.1.0, so this polyfill can't use a direct fall-through to the PHPUnit native + * functionality until the minimum supported PHPUnit version of this library would be PHPUnit 7.1.0.} + * + * @link https://github.com/sebastianbergmann/phpunit/pull/3035 PR which added support for `is_iterable`. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyIterable( $haystack, string $message = '' ) { + if ( \function_exists( 'is_iterable' ) === true + && \version_compare( Autoload::getPHPUnitVersion(), '7.1.0', '>=' ) + ) { + // PHP >= 7.1 with PHPUnit >= 7.1.0. + static::assertContainsOnly( 'iterable', $haystack, true, $message ); + } + else { + // PHP < 7.1 or PHPUnit 6.x/7.0.0. + $exporter = self::getPHPUnitExporterObjectForContainsOnly(); + $msg = \sprintf( 'Failed asserting that %s contains only values of type "iterable".', $exporter->export( $haystack ) ); + + if ( $message !== '' ) { + $msg = $message . \PHP_EOL . $msg; + } + + $hasOnlyIterable = true; + foreach ( $haystack as $value ) { + if ( \is_array( $value ) || $value instanceof Traversable ) { + continue; + } + + $hasOnlyIterable = false; + break; + } + + static::assertTrue( $hasOnlyIterable, $msg ); + } + } + + /** + * Asserts that $haystack does not only contain values of type iterable. + * + * {@internal Support for `iterable` was only added to the `IsType` constraint + * in PHPUnit 7.1.0, so this polyfill can't use a direct fall-through to the PHPUnit native + * functionality until the minimum supported PHPUnit version of this library would be PHPUnit 7.1.0.} + * + * @link https://github.com/sebastianbergmann/phpunit/pull/3035 PR which added support for `is_iterable`. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyIterable( $haystack, string $message = '' ) { + if ( \function_exists( 'is_iterable' ) === true + && \version_compare( Autoload::getPHPUnitVersion(), '7.1.0', '>=' ) + ) { + // PHP >= 7.1 with PHPUnit >= 7.1.0. + static::assertNotContainsOnly( 'iterable', $haystack, true, $message ); + } + else { + // PHP < 7.1 or PHPUnit 6.x/7.0.0. + $exporter = self::getPHPUnitExporterObjectForContainsOnly(); + $msg = \sprintf( 'Failed asserting that %s does not contain only values of type "iterable".', $exporter->export( $haystack ) ); + + if ( $message !== '' ) { + $msg = $message . \PHP_EOL . $msg; + } + + $hasOnlyIterable = true; + foreach ( $haystack as $value ) { + if ( \is_array( $value ) || $value instanceof Traversable ) { + continue; + } + + $hasOnlyIterable = false; + break; + } + + static::assertFalse( $hasOnlyIterable, $msg ); + } + } + + /** + * Asserts that $haystack only contains values of type null. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyNull( $haystack, string $message = '' ) { + static::assertContainsOnly( 'null', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type null. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyNull( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'null', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type numeric. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyNumeric( $haystack, string $message = '' ) { + static::assertContainsOnly( 'numeric', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type numeric. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyNumeric( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'numeric', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type object. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyObject( $haystack, string $message = '' ) { + static::assertContainsOnly( 'object', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type object. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyObject( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'object', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type resource. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyResource( $haystack, string $message = '' ) { + static::assertContainsOnly( 'resource', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type resource. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyResource( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'resource', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type closed resource. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyClosedResource( $haystack, string $message = '' ) { + $exporter = self::getPHPUnitExporterObjectForContainsOnly(); + $msg = \sprintf( 'Failed asserting that %s contains only values of type "resource (closed)".', $exporter->export( $haystack ) ); + + if ( $message !== '' ) { + $msg = $message . \PHP_EOL . $msg; + } + + $hasOnlyClosedResources = true; + foreach ( $haystack as $value ) { + if ( ResourceHelper::isClosedResource( $value ) ) { + continue; + } + + $hasOnlyClosedResources = false; + break; + } + + static::assertTrue( $hasOnlyClosedResources, $msg ); + } + + /** + * Asserts that $haystack does not only contain values of type closed resource. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyClosedResource( $haystack, string $message = '' ) { + $exporter = self::getPHPUnitExporterObjectForContainsOnly(); + $msg = \sprintf( 'Failed asserting that %s does not contain only values of type "resource (closed)".', $exporter->export( $haystack ) ); + + if ( $message !== '' ) { + $msg = $message . \PHP_EOL . $msg; + } + + $hasOnlyClosedResources = true; + foreach ( $haystack as $value ) { + if ( ResourceHelper::isClosedResource( $value ) ) { + continue; + } + + $hasOnlyClosedResources = false; + break; + } + + static::assertFalse( $hasOnlyClosedResources, $msg ); + } + + /** + * Asserts that $haystack only contains values of type scalar. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyScalar( $haystack, string $message = '' ) { + static::assertContainsOnly( 'scalar', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type scalar. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyScalar( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'scalar', $haystack, true, $message ); + } + + /** + * Asserts that $haystack only contains values of type string. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsOnlyString( $haystack, string $message = '' ) { + static::assertContainsOnly( 'string', $haystack, true, $message ); + } + + /** + * Asserts that $haystack does not only contain values of type string. + * + * @param iterable $haystack The variable to test. + * @param string $message Optional failure message to display. + * + * @return void + */ + final public static function assertContainsNotOnlyString( $haystack, string $message = '' ) { + static::assertNotContainsOnly( 'string', $haystack, true, $message ); + } + + /** + * Helper function to obtain an instance of the Exporter class. + * + * @return Exporter|Exporter_In_Phar|Exporter_In_Phar_Old + */ + private static function getPHPUnitExporterObjectForContainsOnly() { + if ( \class_exists( Exporter::class ) ) { + // Composer install or really old PHAR files. + return new Exporter(); + } + elseif ( \class_exists( Exporter_In_Phar::class ) ) { + // PHPUnit PHAR file for 8.5.38+, 9.6.19+, 10.5.17+ and 11.0.10+. + return new Exporter_In_Phar(); + } + + // PHPUnit PHAR file for < 8.5.38, < 9.6.19, < 10.5.17 and < 11.0.10. + return new Exporter_In_Phar_Old(); + } +} diff --git a/src/Polyfills/AssertContainsOnly_Empty.php b/src/Polyfills/AssertContainsOnly_Empty.php new file mode 100644 index 0000000..e2b29c9 --- /dev/null +++ b/src/Polyfills/AssertContainsOnly_Empty.php @@ -0,0 +1,10 @@ += 11.5.0 in which the polyfill is not needed. + * + * @since 3.1.0 + */ +trait AssertContainsOnly {} diff --git a/src/TestCases/TestCasePHPUnitGte8.php b/src/TestCases/TestCasePHPUnitGte8.php index 3b9bde0..930a6a2 100644 --- a/src/TestCases/TestCasePHPUnitGte8.php +++ b/src/TestCases/TestCasePHPUnitGte8.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase as PHPUnit_TestCase; use Yoast\PHPUnitPolyfills\Polyfills\AssertArrayWithListKeys; use Yoast\PHPUnitPolyfills\Polyfills\AssertClosedResource; +use Yoast\PHPUnitPolyfills\Polyfills\AssertContainsOnly; use Yoast\PHPUnitPolyfills\Polyfills\AssertFileEqualsSpecializations; use Yoast\PHPUnitPolyfills\Polyfills\AssertIgnoringLineEndings; use Yoast\PHPUnitPolyfills\Polyfills\AssertionRenames; @@ -31,6 +32,7 @@ abstract class TestCase extends PHPUnit_TestCase { use AssertArrayWithListKeys; use AssertClosedResource; + use AssertContainsOnly; use AssertFileEqualsSpecializations; use AssertIgnoringLineEndings; use AssertionRenames; diff --git a/src/TestCases/TestCasePHPUnitLte7.php b/src/TestCases/TestCasePHPUnitLte7.php index 078a748..e9becbd 100644 --- a/src/TestCases/TestCasePHPUnitLte7.php +++ b/src/TestCases/TestCasePHPUnitLte7.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase as PHPUnit_TestCase; use Yoast\PHPUnitPolyfills\Polyfills\AssertArrayWithListKeys; use Yoast\PHPUnitPolyfills\Polyfills\AssertClosedResource; +use Yoast\PHPUnitPolyfills\Polyfills\AssertContainsOnly; use Yoast\PHPUnitPolyfills\Polyfills\AssertEqualsSpecializations; use Yoast\PHPUnitPolyfills\Polyfills\AssertFileEqualsSpecializations; use Yoast\PHPUnitPolyfills\Polyfills\AssertIgnoringLineEndings; @@ -34,6 +35,7 @@ abstract class TestCase extends PHPUnit_TestCase { use AssertArrayWithListKeys; use AssertClosedResource; + use AssertContainsOnly; use AssertEqualsSpecializations; use AssertFileEqualsSpecializations; use AssertIgnoringLineEndings; diff --git a/src/TestCases/XTestCase.php b/src/TestCases/XTestCase.php index f9762e7..ccba952 100644 --- a/src/TestCases/XTestCase.php +++ b/src/TestCases/XTestCase.php @@ -9,6 +9,7 @@ use PHPUnit\Framework\TestCase as PHPUnit_TestCase; use Yoast\PHPUnitPolyfills\Polyfills\AssertArrayWithListKeys; use Yoast\PHPUnitPolyfills\Polyfills\AssertClosedResource; +use Yoast\PHPUnitPolyfills\Polyfills\AssertContainsOnly; use Yoast\PHPUnitPolyfills\Polyfills\AssertEqualsSpecializations; use Yoast\PHPUnitPolyfills\Polyfills\AssertFileEqualsSpecializations; use Yoast\PHPUnitPolyfills\Polyfills\AssertIgnoringLineEndings; @@ -40,6 +41,7 @@ abstract class XTestCase extends PHPUnit_TestCase { use AssertArrayWithListKeys; use AssertClosedResource; + use AssertContainsOnly; use AssertEqualsSpecializations; use AssertFileEqualsSpecializations; use AssertIgnoringLineEndings; diff --git a/tests/Polyfills/AssertContainsOnlyTest.php b/tests/Polyfills/AssertContainsOnlyTest.php new file mode 100644 index 0000000..e2bacbc --- /dev/null +++ b/tests/Polyfills/AssertContainsOnlyTest.php @@ -0,0 +1,1243 @@ + + */ + public static function dataMixedValues() { + return [ + 'Array with a mix of values' => [ + [ + null, + false, + 10, + 4.34, + 'string', + 'is_callable', + [ 'not', 'empty' ], + new stdClass(), + ], + ], + ]; + } + + /** + * Verify the assertContainsNotOnlyInstancesOf() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyInstancesOfSucceeds( $haystack ) { + $this->assertContainsNotOnlyInstancesOf( stdClass::class, $haystack ); + } + + /** + * Verify the assertContainsNotOnlyInstancesOf() method fails on invalid input. + * + * @return void + */ + public function testAssertContainsNotOnlyInstancesOfFails() { + $pattern = '`(\]|\)) does not contain only values of type "stdClass"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $haystack = [ + new stdClass( 1, 2, 3 ), + new stdClass(), + new stdClass( 'foo' ), + ]; + + self::assertContainsNotOnlyInstancesOf( stdClass::class, $haystack ); + } + + /** + * Verify the assertContainsOnlyArray() method succeeds for valid input. + * + * @dataProvider dataOnlyArray + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyArray' )] + public function testAssertContainsOnlyArraySucceeds( $haystack ) { + self::assertContainsOnlyArray( $haystack ); + } + + /** + * Verify the assertContainsOnlyArray() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyArrayFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "array"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + static::assertContainsOnlyArray( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyArray() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyArraySucceeds( $haystack ) { + static::assertContainsNotOnlyArray( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyArray() method fails on invalid input. + * + * @dataProvider dataOnlyArray + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyArray' )] + public function testAssertContainsNotOnlyArrayFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "array"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyArray( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyArray() { + return [ + 'Array containing only arrays' => [ + [ + [], + [ 1, 2, 3 ], + [ 'foo' => 'bar' ], + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyBool() method succeeds for valid input. + * + * @dataProvider dataOnlyBool + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyBool' )] + public function testAssertContainsOnlyBoolSucceeds( $haystack ) { + $this->assertContainsOnlyBool( $haystack ); + } + + /** + * Verify the assertContainsOnlyBool() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyBoolFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "bool"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsOnlyBool( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyBool() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyBoolSucceeds( $haystack ) { + $this->assertContainsNotOnlyBool( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyBool() method fails on invalid input. + * + * @dataProvider dataOnlyBool + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyBool' )] + public function testAssertContainsNotOnlyBoolFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "bool"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + static::assertContainsNotOnlyBool( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyBool() { + return [ + 'Array containing only booleans' => [ + [ + 0 => false, + 1 => true, + 'foo' => true, + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyCallable() method succeeds for valid input. + * + * @dataProvider dataOnlyCallable + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyCallable' )] + public function testAssertContainsOnlyCallableSucceeds( $haystack ) { + $this->assertContainsOnlyCallable( $haystack ); + } + + /** + * Verify the assertContainsOnlyCallable() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyCallableFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "callable"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsOnlyCallable( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyCallable() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyCallableSucceeds( $haystack ) { + $this->assertContainsNotOnlyCallable( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyCallable() method fails on invalid input. + * + * @dataProvider dataOnlyCallable + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyCallable' )] + public function testAssertContainsNotOnlyCallableFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "callable"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyCallable( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyCallable() { + return [ + 'Array containing only callables' => [ + [ + 'is_string', + [ self::class, 'dummyCallable' ], + ], + ], + ]; + } + + /** + * Dummy method to have a callable method available. + * + * @return void + */ + public static function dummyCallable() { + // Nothing to see here. + } + + /** + * Verify the assertContainsOnlyFloat() method succeeds for valid input. + * + * @dataProvider dataOnlyFloat + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyFloat' )] + public function testAssertContainsOnlyFloatSucceeds( $haystack ) { + self::assertContainsOnlyFloat( $haystack ); + } + + /** + * Verify the assertContainsOnlyFloat() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyFloatFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "float"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsOnlyFloat( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyFloat() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyFloatSucceeds( $haystack ) { + $this->assertContainsNotOnlyFloat( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyFloat() method fails on invalid input. + * + * @dataProvider dataOnlyFloat + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyFloat' )] + public function testAssertContainsNotOnlyFloatFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "float"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyFloat( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyFloat() { + return [ + 'Array containing only floats' => [ + [ + 0.0, + 3.5, + -0.5645, + 8E7, + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyInt() method succeeds for valid input. + * + * @dataProvider dataOnlyInt + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyInt' )] + public function testAssertContainsOnlyIntSucceeds( $haystack ) { + $this->assertContainsOnlyInt( $haystack ); + } + + /** + * Verify the assertContainsOnlyInt() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyIntFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "int"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsOnlyInt( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyInt() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyIntSucceeds( $haystack ) { + $this->assertContainsNotOnlyInt( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyInt() method fails on invalid input. + * + * @dataProvider dataOnlyInt + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyInt' )] + public function testAssertContainsNotOnlyIntFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "int"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $this->assertContainsNotOnlyInt( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyInt() { + return [ + 'Array containing only integers' => [ + [ + 0, + 10, + -2, + 0b010100, + 0x7AB, + \PHP_INT_MAX, + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyIterable() method succeeds for valid input. + * + * @dataProvider dataOnlyIterable + * + * @param array> $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyIterable' )] + public function testAssertContainsOnlyIterableSucceeds( $haystack ) { + $this->assertContainsOnlyIterable( $haystack ); + } + + /** + * Verify the assertContainsOnlyIterable() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyIterableFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "iterable"\.`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $this->assertContainsOnlyIterable( $haystack ); + } + + /** + * Verify that the assertContainsOnlyIterable() method fails a test with the correct custom failure message, + * when the custom $message parameter has been passed. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyIterableFailsWithCustomMessage( $haystack ) { + $pattern = '`^This assertion failed for reason XYZ\R`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $this->assertContainsOnlyIterable( $haystack, 'This assertion failed for reason XYZ' ); + } + + /** + * Verify the assertContainsNotOnlyIterable() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyIterableSucceeds( $haystack ) { + $this->assertContainsNotOnlyIterable( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyIterable() method fails on invalid input. + * + * @dataProvider dataOnlyIterable + * + * @param array> $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyIterable' )] + public function testAssertContainsNotOnlyIterableFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "iterable"\.`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + static::assertContainsNotOnlyIterable( $haystack ); + } + + /** + * Verify that the assertContainsNotOnlyIterable() method fails a test with the correct custom failure message, + * when the custom $message parameter has been passed. + * + * @dataProvider dataOnlyIterable + * + * @param array> $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyIterable' )] + public function testAssertContainsNotOnlyIterableFailsWithCustomMessage( $haystack ) { + $pattern = '`^This assertion failed for reason XYZ\R`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyIterable( $haystack, 'This assertion failed for reason XYZ' ); + } + + /** + * Data provider. + * + * @return array>> + */ + public static function dataOnlyIterable() { + return [ + 'Array containing only iterables' => [ + [ + [], + [ 1, 2, 3 ], + [ 'foo' => 'bar' ], + new EmptyIterator(), + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyNull() method succeeds for valid input. + * + * @dataProvider dataOnlyNull + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyNull' )] + public function testAssertContainsOnlyNullSucceeds( $haystack ) { + self::assertContainsOnlyNull( $haystack ); + } + + /** + * Verify the assertContainsOnlyNull() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyNullFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "null"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsOnlyNull( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyNull() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyNullSucceeds( $haystack ) { + $this->assertContainsNotOnlyNull( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyNull() method fails on invalid input. + * + * @dataProvider dataOnlyNull + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyNull' )] + public function testAssertContainsNotOnlyNullFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "null"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyNull( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyNull() { + return [ + 'Array containing only nulls' => [ + [ + null, + null, + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyNumeric() method succeeds for valid input. + * + * @dataProvider dataOnlyNumeric + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyNumeric' )] + public function testAssertContainsOnlyNumericSucceeds( $haystack ) { + self::assertContainsOnlyNumeric( $haystack ); + } + + /** + * Verify the assertContainsOnlyNumeric() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyNumericFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "numeric"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + static::assertContainsOnlyNumeric( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyNumeric() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyNumericSucceeds( $haystack ) { + $this->assertContainsNotOnlyNumeric( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyNumeric() method fails on invalid input. + * + * @dataProvider dataOnlyNumeric + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyNumeric' )] + public function testAssertContainsNotOnlyNumericFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "numeric"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyNumeric( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyNumeric() { + return [ + 'Array containing only numerics' => [ + [ + '0', + '12344', + 0, + 1235, + 0.0, + -12.4, + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyObject() method succeeds for valid input. + * + * @dataProvider dataOnlyObject + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyObject' )] + public function testAssertContainsOnlyObjectSucceeds( $haystack ) { + $this->assertContainsOnlyObject( $haystack ); + } + + /** + * Verify the assertContainsOnlyObject() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyObjectFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "object"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsOnlyObject( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyObject() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyObjectSucceeds( $haystack ) { + $this->assertContainsNotOnlyObject( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyObject() method fails on invalid input. + * + * @dataProvider dataOnlyObject + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyObject' )] + public function testAssertContainsNotOnlyObjectFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "object"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyObject( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyObject() { + return [ + 'Array containing only objects' => [ + [ + new stdClass(), + new EmptyIterator(), + new DateTime(), + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyResource() method succeeds for valid input. + * + * @return void + */ + public function testAssertContainsOnlyResourceSucceeds() { + $this->assertContainsOnlyResource( [ self::$openResource, self::$closedResource ] ); + } + + /** + * Verify the assertContainsOnlyResource() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyResourceFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "resource"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsOnlyResource( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyResource() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyResourceSucceeds( $haystack ) { + static::assertContainsNotOnlyResource( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyResource() method fails on invalid input. + * + * @return void + */ + public function testAssertContainsNotOnlyResourceFails() { + $pattern = '`(\]|\)) does not contain only values of type "resource"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $this->assertContainsNotOnlyResource( [ self::$openResource, self::$closedResource ] ); + } + + /** + * Verify the assertContainsOnlyClosedResource() method succeeds for valid input. + * + * @return void + */ + public function testAssertContainsOnlyClosedResourceSucceeds() { + $this->assertContainsOnlyClosedResource( [ self::$closedResource ] ); + } + + /** + * Verify the assertContainsOnlyClosedResource() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyClosedResourceFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "resource \(closed\)"\.`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsOnlyClosedResource( $haystack ); + } + + /** + * Verify that the assertContainsOnlyClosedResource() method fails a test with the correct custom failure message, + * when the custom $message parameter has been passed. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyClosedResourceFailsWithCustomMessage( $haystack ) { + $pattern = '`^This assertion failed for reason XYZ\R`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $this->assertContainsOnlyClosedResource( $haystack, 'This assertion failed for reason XYZ' ); + } + + /** + * Verify the assertContainsNotOnlyClosedResource() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyClosedResourceSucceeds( $haystack ) { + self::assertContainsNotOnlyClosedResource( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyClosedResource() method fails on invalid input. + * + * @return void + */ + public function testAssertContainsNotOnlyClosedResourceFails() { + $pattern = '`(\]|\)) does not contain only values of type "resource \(closed\)"\.`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyClosedResource( [ self::$closedResource ] ); + } + + /** + * Verify that the assertContainsNotOnlyClosedResource() method fails a test with the correct custom failure message, + * when the custom $message parameter has been passed. + * + * @return void + */ + public function testAssertContainsNotOnlyClosedResourceFailsWithCustomMessage() { + $pattern = '`^This assertion failed for reason XYZ\R`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyClosedResource( [ self::$closedResource ], 'This assertion failed for reason XYZ' ); + } + + /** + * Verify the assertContainsOnlyScalar() method succeeds for valid input. + * + * @dataProvider dataOnlyScalar + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyScalar' )] + public function testAssertContainsOnlyScalarSucceeds( $haystack ) { + self::assertContainsOnlyScalar( $haystack ); + } + + /** + * Verify the assertContainsOnlyScalar() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyScalarFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "scalar"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $this->assertContainsOnlyScalar( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyScalar() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyScalarSucceeds( $haystack ) { + static::assertContainsNotOnlyScalar( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyScalar() method fails on invalid input. + * + * @dataProvider dataOnlyScalar + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyScalar' )] + public function testAssertContainsNotOnlyScalarFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "scalar"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $this->assertContainsNotOnlyScalar( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyScalar() { + return [ + 'Array containing only scalars' => [ + [ + 'string', + true, + 10, + -1.3, + '', + 0, + ], + ], + ]; + } + + /** + * Verify the assertContainsOnlyString() method succeeds for valid input. + * + * @dataProvider dataOnlyString + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyString' )] + public function testAssertContainsOnlyStringSucceeds( $haystack ) { + static::assertContainsOnlyString( $haystack ); + } + + /** + * Verify the assertContainsOnlyString() method fails on invalid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsOnlyStringFails( $haystack ) { + $pattern = '`(\]|\)) contains only values of type "string"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + $this->assertContainsOnlyString( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyString() method succeeds for valid input. + * + * @dataProvider dataMixedValues + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataMixedValues' )] + public function testAssertContainsNotOnlyStringSucceeds( $haystack ) { + $this->assertContainsNotOnlyString( $haystack ); + } + + /** + * Verify the assertContainsNotOnlyString() method fails on invalid input. + * + * @dataProvider dataOnlyString + * + * @param array $haystack Haystack. + * + * @return void + */ + #[DataProvider( 'dataOnlyString' )] + public function testAssertContainsNotOnlyStringFails( $haystack ) { + $pattern = '`(\]|\)) does not contain only values of type "string"\.$`'; + + $this->expectException( AssertionFailedError::class ); + $this->expectExceptionMessageMatches( $pattern ); + + self::assertContainsNotOnlyString( $haystack ); + } + + /** + * Data provider. + * + * @return array> + */ + public static function dataOnlyString() { + return [ + 'Array containing only strings' => [ + [ + '', + 'foo', + 'bar', + 'baz', + ], + ], + ]; + } +} diff --git a/tests/TestCases/TestCaseTestTrait.php b/tests/TestCases/TestCaseTestTrait.php index 50a0ca2..7e839e8 100644 --- a/tests/TestCases/TestCaseTestTrait.php +++ b/tests/TestCases/TestCaseTestTrait.php @@ -190,4 +190,13 @@ final public function testAvailabilityExpectUserDeprecation() { \trigger_error( 'This is a deprecation notice', \E_USER_DEPRECATED ); } + + /** + * Verify availability of trait polyfilled PHPUnit methods [21]. + * + * @return void + */ + final public function testAvailabilityAssertContainsOnly() { + $this->assertContainsOnlyBool( [ true, false ] ); + } }