diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 5fe8e1c..1edb2b0 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
- php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', 'nightly']
+ php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', 'nightly']
continue-on-error: ${{ matrix.php == 'nightly' }}
@@ -62,10 +62,6 @@ jobs:
# Bust the cache at least once a month - output format: YYYY-MM.
custom-cache-suffix: $(date -u "+%Y-%m")
- - name: "Lint PHP files against parse errors - PHP < 7.0"
- if: ${{ matrix.php != 'nightly' && matrix.php < 7.0 }}
- run: composer lint-lt70 -- --checkstyle | cs2pr
-
- name: "Lint PHP files against parse errors - PHP 7.0"
if: ${{ matrix.php == '7.0' }}
run: composer lint70
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e91ece7..3c754c0 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
- php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
+ php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
phpunit: ['auto']
coverage: [true]
experimental: [false]
@@ -28,14 +28,10 @@ jobs:
include:
# Test against a version on the low-end of the PHPUnit versions supported for each PHP version.
# Using the Composer `--prefer-lowest` option is, unfortunately, not viable, as
- # it would result PHP 5.6 - 7.4 all using PHPUnit 5.7.21, which is not the intention.
+ # it would result PHP 7.0 - 7.4 all using PHPUnit 5.7.21, which is not the intention.
# It also would run into trouble with PHP 8.5.12 being used on PHP 8.0+, while the
# 8.5.12 release still contained a bug which makes it incompatible with PHP 8.1+,
# even though it officially allows for it..
- - php: '5.6'
- phpunit: '5.7.21'
- coverage: true
- experimental: false
- php: '7.0'
phpunit: '5.7.27'
coverage: true
@@ -211,9 +207,9 @@ jobs:
# This should be sufficient to record the coverage for the PHAR specific code.
# PHPUnit 5 is only supported for PHPUnit 5.7.21-latest.
- - php: '5.6'
+ - php: '7.0'
phpunit: '5.7.21'
- - php: '5.6'
+ - php: '7.0'
phpunit: '5'
- php: '7.1'
phpunit: '5.7.21'
diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist
index e11b822..0909cae 100644
--- a/.phpcs.xml.dist
+++ b/.phpcs.xml.dist
@@ -54,7 +54,6 @@
-
@@ -68,10 +67,6 @@
polyfilled functionality from not being flagged in this repo. -->
5
-
-
-
-
@@ -179,22 +174,18 @@
/tests/Polyfills/Fixtures/*\.php$
-
-
- /tests/Polyfills/Fixtures/ChildValueObject\.php$
- /tests/Polyfills/Fixtures/ValueObject\.php$
+
+
/tests/Polyfills/Fixtures/ValueObjectParamNotRequired\.php$
- /tests/Polyfills/Fixtures/ValueObjectUnion\.php$
+
+
+ /tests/Polyfills/Fixtures/ValueObjectNullableReturnType\.php$
/tests/Polyfills/Fixtures/ValueObjectUnion\.php$
- /tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType\.php$
-
-
- /tests/Polyfills/Fixtures/ValueObjectParamNotRequired\.php$
-
- /tests/Polyfills/Fixtures/ValueObject\.php$
+
+ /tests/Polyfills/Fixtures/ValueObjectUnionReturnType\.php$
diff --git a/README.md b/README.md
index e312045..ef12396 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@ Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit
Requirements
------------
-* PHP 5.6 or higher.
+* PHP 7.0 or higher.
* [PHPUnit] 5.7 - 10.x (automatically required via Composer).
[PHPUnit]: https://packagist.org/packages/phpunit/phpunit
@@ -391,17 +391,10 @@ This assertion expects an object to contain a comparator method in the object it
The `assertObjectEquals()` assertion was introduced in PHPUnit 9.4.0.
-> :information_source: Due to [limitations in how this assertion is implemented in PHPUnit] itself, it is currently not possible to create a single comparator method which will be compatible with both PHP < 7.0 and PHP 7.0 or higher.
->
-> In effect two declarations of the same object would be needed to be compatible with PHP < 7.0 and PHP 7.0 and higher and still allow for testing the object using the `assertObjectEquals()` assertion.
->
-> Due to this limitation, it is recommended to only use this assertion if the minimum supported PHP version of a project is PHP 7.0 or higher; or if the project does not run its tests on PHPUnit >= 9.4.0.
->
-> The implementation of this assertion in the Polyfills is PHP cross-version compatible.
-
-[limitations in how this assertion is implemented in PHPUnit]: https://github.com/sebastianbergmann/phpunit/issues/4707
+> :information_source: In PHPUnit Polyfills 1.x and 2.x, the polyfill for this assertion had [some limitations][assertobjectequals-limitations]. These limitations are no longer present in PHPUnit Polyfills 3.x and the assertion now matches the PHPUnit native implementation.
[`Assert::assertObjectEquals()`]: https://docs.phpunit.de/en/main/assertions.html#assertobjectequals
+[assertobjectequals-limitations]: https://github.com/Yoast/PHPUnit-Polyfills/?tab=readme-ov-file#phpunit--940-yoastphpunitpolyfillspolyfillsassertobjectequals
#### PHPUnit < 10.0.0: `Yoast\PHPUnitPolyfills\Polyfills\AssertIgnoringLineEndings`
diff --git a/composer.json b/composer.json
index 67e6a1b..4afa0cd 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,7 @@
"security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy"
},
"require": {
- "php": ">=5.6",
+ "php": ">=7.0",
"phpunit/phpunit": "^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0"
},
"require-dev": {
@@ -59,22 +59,19 @@
},
"scripts": {
"lint7": [
- "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude src/Exceptions/Error.php --exclude src/Exceptions/TypeError.php --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php"
+ "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionReturnType.php"
],
"lint70": [
- "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude src/Exceptions/Error.php --exclude src/Exceptions/TypeError.php --exclude tests/Polyfills/Fixtures/ValueObjectParamNotRequired.php --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php"
- ],
- "lint-lt70": [
- "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude src/TestCases/TestCasePHPUnitGte8.php --exclude src/TestListeners/TestListenerDefaultImplementationPHPUnitGte7.php --exclude tests/Polyfills/Fixtures/ChildValueObject.php --exclude tests/Polyfills/Fixtures/ValueObject.php --exclude tests/Polyfills/Fixtures/ValueObjectParamNotRequired.php --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php"
+ "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude src/Exceptions/Error.php --exclude src/Exceptions/TypeError.php --exclude tests/Polyfills/Fixtures/ValueObjectParamNotRequired.php --exclude tests/Polyfills/Fixtures/ValueObjectNullableReturnType.php --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionReturnType.php"
],
"lint-gte80": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git"
],
"lint-gte84": [
- "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude tests/Polyfills/Fixtures/ValueObjectNoReturnType.php"
+ "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git"
],
"check-cs": [
- "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --runtime-set testVersion 5.6-"
+ "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --runtime-set testVersion 7.0-"
],
"fix-cs": [
"@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf"
@@ -95,7 +92,6 @@
"scripts-descriptions": {
"lint7": "Check the PHP files for parse errors. (PHP 7.1 - 7.4)",
"lint70": "Check the PHP files for parse errors. (PHP 7.0)",
- "lint-lt70": "Check the PHP files for parse errors. (PHP < 7.0)",
"lint-gte80": "Check the PHP files for parse errors. (PHP 8.0 - 8.3)",
"lint-gte84": "Check the PHP files for parse errors. (PHP 8.4+)",
"check-cs": "Check the PHP files for code style violations and best practices.",
diff --git a/phpunitpolyfills-autoload.php b/phpunitpolyfills-autoload.php
index 4b1e743..363ef49 100644
--- a/phpunitpolyfills-autoload.php
+++ b/phpunitpolyfills-autoload.php
@@ -29,22 +29,6 @@ final class Autoload {
* @return bool
*/
public static function load( $className ) {
- /*
- * Polyfill two PHP 7.0 classes.
- * The autoloader will only be called for these if these classes don't already
- * exist in PHP natively.
- */
- if ( $className === 'Error' || $className === 'TypeError' ) {
- $file = \realpath( __DIR__ . '/src/Exceptions/' . $className . '.php' );
-
- if ( \is_string( $file ) && \file_exists( $file ) === true ) {
- require_once $file;
- return true;
- }
-
- return false;
- }
-
// Only load classes belonging to this library.
if ( \stripos( $className, 'Yoast\PHPUnitPolyfills' ) !== 0 ) {
return false;
diff --git a/src/Exceptions/Error.php b/src/Exceptions/Error.php
deleted file mode 100644
index 6a44e67..0000000
--- a/src/Exceptions/Error.php
+++ /dev/null
@@ -1,8 +0,0 @@
-$method($expected)` returns boolean true.
+ * - The method must have a declared bool return type.
*
* @param object $expected Expected value.
* @param object $actual The value to test.
@@ -103,14 +100,49 @@ final public static function assertObjectEquals( $expected, $actual, $method = '
$reflMethod = $reflObject->getMethod( $method );
/*
- * As the next step, PHPUnit natively would validate the return type,
- * but as return type declarations is a PHP 7.0+ feature, the polyfill
- * skips this check in favour of checking the type of the actual
- * returned value.
- *
- * Also see the upstream discussion about this:
- * {@link https://github.com/sebastianbergmann/phpunit/issues/4707}
+ * Comparator method return type requirements validation.
*/
+ $returnTypeError = \sprintf(
+ 'Comparison method %s::%s() does not declare bool return type.',
+ \get_class( $actual ),
+ $method
+ );
+
+ if ( $reflMethod->hasReturnType() === false ) {
+ throw new InvalidComparisonMethodException( $returnTypeError );
+ }
+
+ $returnType = $reflMethod->getReturnType();
+
+ if ( \class_exists( 'ReflectionNamedType' ) ) {
+ // PHP >= 7.1: guard against union/intersection return types.
+ if ( ( $returnType instanceof ReflectionNamedType ) === false ) {
+ throw new InvalidComparisonMethodException( $returnTypeError );
+ }
+ }
+ elseif ( ( $returnType instanceof ReflectionType ) === false ) {
+ /*
+ * PHP 7.0.
+ * Checking for `ReflectionType` will not throw an error on union types,
+ * but then again union types are not supported on PHP 7.0.
+ */
+ throw new InvalidComparisonMethodException( $returnTypeError );
+ }
+
+ if ( $returnType->allowsNull() === true ) {
+ throw new InvalidComparisonMethodException( $returnTypeError );
+ }
+
+ if ( \method_exists( $returnType, 'getName' ) ) {
+ // PHP 7.1+.
+ if ( $returnType->getName() !== 'bool' ) {
+ throw new InvalidComparisonMethodException( $returnTypeError );
+ }
+ }
+ elseif ( (string) $returnType !== 'bool' ) {
+ // PHP 7.0.
+ throw new InvalidComparisonMethodException( $returnTypeError );
+ }
/*
* Comparator method parameter requirements validation.
@@ -142,55 +174,31 @@ final public static function assertObjectEquals( $expected, $actual, $method = '
$reflParameter = $reflMethod->getParameters()[0];
- if ( \method_exists( $reflParameter, 'hasType' ) ) {
- // PHP >= 7.0.
- $hasType = $reflParameter->hasType();
- if ( $hasType === false ) {
+ $hasType = $reflParameter->hasType();
+ if ( $hasType === false ) {
+ throw new InvalidComparisonMethodException( $noDeclaredTypeError );
+ }
+
+ $type = $reflParameter->getType();
+ if ( \class_exists( 'ReflectionNamedType' ) ) {
+ // PHP >= 7.1.
+ if ( ( $type instanceof ReflectionNamedType ) === false ) {
throw new InvalidComparisonMethodException( $noDeclaredTypeError );
}
- $type = $reflParameter->getType();
- if ( \class_exists( 'ReflectionNamedType' ) ) {
- // PHP >= 7.1.
- if ( ( $type instanceof ReflectionNamedType ) === false ) {
- throw new InvalidComparisonMethodException( $noDeclaredTypeError );
- }
-
- $typeName = $type->getName();
- }
- else {
- /*
- * PHP 7.0.
- * Checking for `ReflectionType` will not throw an error on union types,
- * but then again union types are not supported on PHP 7.0.
- */
- if ( ( $type instanceof ReflectionType ) === false ) {
- throw new InvalidComparisonMethodException( $noDeclaredTypeError );
- }
-
- $typeName = (string) $type;
- }
+ $typeName = $type->getName();
}
else {
- // PHP < 7.0.
- try {
- /*
- * Using `ReflectionParameter::getClass()` will trigger an autoload of the class,
- * but that's okay as for a valid class type that would be triggered on the
- * function call to the $method (at the end of this assertion) anyway.
- */
- $hasType = $reflParameter->getClass();
- } catch ( ReflectionException $e ) {
- // Class with a type declaration for a non-existent class.
- throw new InvalidComparisonMethodException( $notAcceptableTypeError );
- }
-
- if ( ( $hasType instanceof ReflectionClass ) === false ) {
- // Array or callable type.
+ /*
+ * PHP 7.0.
+ * Checking for `ReflectionType` will not throw an error on union types,
+ * but then again union types are not supported on PHP 7.0.
+ */
+ if ( ( $type instanceof ReflectionType ) === false ) {
throw new InvalidComparisonMethodException( $noDeclaredTypeError );
}
- $typeName = $hasType->name;
+ $typeName = (string) $type;
}
/*
@@ -209,16 +217,6 @@ final public static function assertObjectEquals( $expected, $actual, $method = '
*/
$result = $actual->{$method}( $expected );
- if ( \is_bool( $result ) === false ) {
- throw new InvalidComparisonMethodException(
- \sprintf(
- 'Comparison method %s::%s() does not return a boolean value.',
- \get_class( $actual ),
- $method
- )
- );
- }
-
$msg = \sprintf(
'Failed asserting that two objects are equal. The objects are not equal according to %s::%s()',
\get_class( $actual ),
diff --git a/tests/Polyfills/AssertIgnoringLineEndingsTest.php b/tests/Polyfills/AssertIgnoringLineEndingsTest.php
index 8f45b06..36945a8 100644
--- a/tests/Polyfills/AssertIgnoringLineEndingsTest.php
+++ b/tests/Polyfills/AssertIgnoringLineEndingsTest.php
@@ -47,7 +47,7 @@ public function testAssertStringEqualsStringIgnoringLineEndingsThrowsTypeErrorOn
$msg = 'assertStringEqualsStringIgnoringLineEndings(): Argument #1 ($expected) must be of type string, ';
}
else {
- // PHP 5/7.
+ // PHP 7.
$msg = 'Argument 1 passed to assertStringEqualsStringIgnoringLineEndings() must be of type string, ';
}
@@ -75,7 +75,7 @@ public function testAssertStringEqualsStringIgnoringLineEndingsThrowsTypeErrorOn
$msg = 'assertStringEqualsStringIgnoringLineEndings(): Argument #2 ($actual) must be of type string, ';
}
else {
- // PHP 5/7.
+ // PHP 7.
$msg = 'Argument 2 passed to assertStringEqualsStringIgnoringLineEndings() must be of type string, ';
}
@@ -221,7 +221,7 @@ public function testAssertStringContainsStringIgnoringLineEndingsThrowsTypeError
$msg = 'assertStringContainsStringIgnoringLineEndings(): Argument #1 ($needle) must be of type string, ';
}
else {
- // PHP 5/7.
+ // PHP 7.
$msg = 'Argument 1 passed to assertStringContainsStringIgnoringLineEndings() must be of type string, ';
}
@@ -249,7 +249,7 @@ public function testAssertStringContainsStringIgnoringLineEndingsThrowsTypeError
$msg = 'assertStringContainsStringIgnoringLineEndings(): Argument #2 ($haystack) must be of type string, ';
}
else {
- // PHP 5/7.
+ // PHP 7.
$msg = 'Argument 2 passed to assertStringContainsStringIgnoringLineEndings() must be of type string, ';
}
diff --git a/tests/Polyfills/AssertObjectEqualsPHPUnitLt940Test.php b/tests/Polyfills/AssertObjectEqualsPHPUnitLt940Test.php
deleted file mode 100644
index 596def2..0000000
--- a/tests/Polyfills/AssertObjectEqualsPHPUnitLt940Test.php
+++ /dev/null
@@ -1,345 +0,0 @@
-=' ) ) {
- $this->markTestSkipped( 'This test can not be run with the PHPUnit native implementation of assertObjectEquals()' );
- }
-
- if ( \version_compare( \PHP_VERSION_ID, '8.3.99', '>' ) ) {
- $this->markTestSkipped( 'This test can not be run on PHP 8.4 or higher as PHPUnit < 9.4.0 is not compatible with PHP 8.4' );
- }
- }
-
- /**
- * Verify availability of the assertObjectEquals() method.
- *
- * @return void
- */
- public function testAssertObjectEquals() {
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual );
- }
-
- /**
- * Verify behaviour when passing the $method parameter.
- *
- * @return void
- */
- public function testAssertObjectEqualsCustomMethodName() {
- $expected = new ValueObjectNoReturnType( 'different name' );
- $actual = new ValueObjectNoReturnType( 'different name' );
- $this->assertObjectEquals( $expected, $actual, 'nonDefaultName' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $expected parameter is not an object.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnExpectedNotObject() {
- $pattern = '`^Argument 1 passed to [^\s]*assertObjectEquals\(\) must be an object, string given`';
-
- $this->expectException( TypeError::class );
- $this->expectExceptionMessageMatches( $pattern );
-
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( 'className', $actual );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $actual parameter is not an object.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnActualNotObject() {
- $pattern = '`^Argument 2 passed to [^\s]*assertObjectEquals\(\) must be an object, string given`';
-
- $this->expectException( TypeError::class );
- $this->expectExceptionMessageMatches( $pattern );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, 'className' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $method parameter is not
- * juggleable to a string.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnMethodNotJuggleableToString() {
- $pattern = '`^Argument 3 passed to [^\s]*assertObjectEquals\(\) must be of the type string, array given`';
-
- $this->expectException( TypeError::class );
- $this->expectExceptionMessageMatches( $pattern );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual, [] );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $actual object
- * does not contain a method called $method.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnMethodNotDeclared() {
- $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::doesNotExist() does not exist.';
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual, 'doesNotExist' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $method accepts more than one parameter.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnMethodAllowsForMoreParams() {
- $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::equalsTwoParams() does not declare exactly one parameter.';
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual, 'equalsTwoParams' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $method is not a required parameter.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnMethodParamNotRequired() {
- $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::equalsParamNotRequired() does not declare exactly one parameter.';
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual, 'equalsParamNotRequired' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $method parameter
- * does not have a type declaration.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnMethodParamMissingTypeDeclaration() {
- $msg = 'Parameter of comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::equalsParamNoType() does not have a declared type.';
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual, 'equalsParamNoType' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $method parameter
- * has a PHP 8.0+ union type declaration.
- *
- * @requires PHP 8.0
- *
- * @return void
- */
- #[RequiresPhp( '8.0' )]
- public function testAssertObjectEqualsFailsOnMethodParamHasUnionTypeDeclaration() {
- $msg = 'Parameter of comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectUnionNoReturnType::equalsParamUnionType() does not have a declared type.';
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectUnionNoReturnType( 'test' );
- $actual = new ValueObjectUnionNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual, 'equalsParamUnionType' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $method parameter
- * does not have a class-based type declaration.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnMethodParamNonClassTypeDeclaration() {
- $msg = 'is not an accepted argument type for comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::equalsParamNonClassType().';
- if ( \PHP_VERSION_ID < 70000 ) {
- $msg = 'Parameter of comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::equalsParamNonClassType() does not have a declared type.';
- }
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual, 'equalsParamNonClassType' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the $method parameter
- * has a class-based type declaration, but for a class which doesn't exist.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnMethodParamNonExistentClassTypeDeclaration() {
- $msg = 'is not an accepted argument type for comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::equalsParamNonExistentClassType().';
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( $expected, $actual, 'equalsParamNonExistentClassType' );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when $expected is not
- * an instance of the type declared for the $method parameter.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnMethodParamTypeMismatch() {
- $msg = 'is not an accepted argument type for comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::equals().';
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $actual = new ValueObjectNoReturnType( 'test' );
- $this->assertObjectEquals( new stdClass(), $actual );
- }
-
- /**
- * Verify that the assertObjectEquals() method throws an error when the declared return type/
- * the return value is not boolean.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnNonBooleanReturnValue() {
- $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNoReturnType::equalsNonBooleanReturnType() does not return a boolean value.';
-
- $this->expectException( self::COMPARATOR_EXCEPTION );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectNoReturnType( 100 );
- $actual = new ValueObjectNoReturnType( 100 );
- $this->assertObjectEquals( $expected, $actual, 'equalsNonBooleanReturnType' );
- }
-
- /**
- * Verify that the assertObjectEquals() method fails a test when a call to method
- * determines that the objects are not equal.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsAsNotEqual() {
- $msg = 'Failed asserting that two objects are equal.';
-
- $this->expectException( $this->getAssertionFailedExceptionName() );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'testing... 1..2..3' );
- $this->assertObjectEquals( $expected, $actual );
- }
-
- /**
- * Verify that the assertObjectEquals() method fails a test with a custom failure message, when a call
- * to the method determines that the objects are not equal and the custom $message parameter has been passed.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsAsNotEqualWithCustomMessage() {
- $pattern = '`^This assertion failed for reason XYZ\s+Failed asserting that two objects are equal\.`';
-
- $this->expectException( $this->getAssertionFailedExceptionName() );
- $this->expectExceptionMessageMatches( $pattern );
-
- $expected = new ValueObjectNoReturnType( 'test' );
- $actual = new ValueObjectNoReturnType( 'testing... 1..2..3' );
- $this->assertObjectEquals( $expected, $actual, 'equals', 'This assertion failed for reason XYZ' );
- }
-
- /**
- * Helper function: retrieve the name of the "assertion failed" exception to expect (PHPUnit cross-version).
- *
- * @return string
- */
- public function getAssertionFailedExceptionName() {
- $exception = AssertionFailedError::class;
- if ( \class_exists( PHPUnit_Framework_AssertionFailedError::class ) ) {
- // PHPUnit < 6.
- $exception = PHPUnit_Framework_AssertionFailedError::class;
- }
-
- return $exception;
- }
-}
diff --git a/tests/Polyfills/AssertObjectEqualsTest.php b/tests/Polyfills/AssertObjectEqualsTest.php
index ca754ff..3d78a90 100644
--- a/tests/Polyfills/AssertObjectEqualsTest.php
+++ b/tests/Polyfills/AssertObjectEqualsTest.php
@@ -20,23 +20,17 @@
use Yoast\PHPUnitPolyfills\Polyfills\ExpectExceptionMessageMatches;
use Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ChildValueObject;
use Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObject;
+use Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNullableReturnType;
use Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectParamNotRequired;
use Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectUnion;
+use Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectUnionReturnType;
/**
* Availability test for the function polyfilled by the AssertObjectEquals trait.
*
- * Due to the use of return types in the classes under test (fixtures), these
- * tests can only run on PHP 7.0 and higher.
- *
- * The `AssertObjectEqualsPHPUnitLt940Test` class mirrors this test class.
- *
* @covers \Yoast\PHPUnitPolyfills\Polyfills\AssertObjectEquals
- *
- * @requires PHP 7.0
*/
#[CoversClass( AssertObjectEquals::class )]
-#[RequiresPhp( '7.0' )]
final class AssertObjectEqualsTest extends TestCase {
use AssertObjectEquals;
@@ -109,7 +103,7 @@ public function testAssertObjectEqualsFailsOnExpectedNotObject() {
$this->expectExceptionMessage( $msg );
}
else {
- // PHP 5/7 or PHP 8 with the polyfill.
+ // PHP 7 or PHP 8 with the polyfill.
$pattern = '`^Argument 1 passed to [^\s]*assertObjectEquals\(\) must be an object, string given`';
$this->expectExceptionMessageMatches( $pattern );
}
@@ -133,7 +127,7 @@ public function testAssertObjectEqualsFailsOnActualNotObject() {
$this->expectExceptionMessage( $msg );
}
else {
- // PHP 5/7.
+ // PHP 7.
$pattern = '`^Argument 2 passed to [^\s]*assertObjectEquals\(\) must be an object, string given`';
$this->expectExceptionMessageMatches( $pattern );
}
@@ -158,7 +152,7 @@ public function testAssertObjectEqualsFailsOnMethodNotJuggleableToString() {
$this->expectExceptionMessage( $msg );
}
else {
- // PHP 5/7.
+ // PHP 7.
$pattern = '`^Argument 3 passed to [^\s]*assertObjectEquals\(\) must be of the type string, array given`';
$this->expectExceptionMessageMatches( $pattern );
}
@@ -191,6 +185,100 @@ public function testAssertObjectEqualsFailsOnMethodNotDeclared() {
$this->assertObjectEquals( $expected, $actual, 'doesNotExist' );
}
+ /**
+ * Verify that the assertObjectEquals() method throws an error when no return type is declared.
+ *
+ * @return void
+ */
+ public function testAssertObjectEqualsFailsOnMissingReturnType() {
+ $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObject::equalsMissingReturnType() does not declare bool return type.';
+
+ $exception = self::COMPARATOR_EXCEPTION;
+ if ( \class_exists( ComparisonMethodDoesNotDeclareBoolReturnTypeException::class ) ) {
+ // PHPUnit > 9.4.0.
+ $exception = ComparisonMethodDoesNotDeclareBoolReturnTypeException::class;
+ }
+
+ $this->expectException( $exception );
+ $this->expectExceptionMessage( $msg );
+
+ $expected = new ValueObject( 100 );
+ $actual = new ValueObject( 100 );
+ $this->assertObjectEquals( $expected, $actual, 'equalsMissingReturnType' );
+ }
+
+ /**
+ * Verify that the assertObjectEquals() method throws an error when the declared return type in a union, intersection or DNF type.
+ *
+ * @requires PHP 8.0
+ *
+ * @return void
+ */
+ #[RequiresPhp( '8.0' )]
+ public function testAssertObjectEqualsFailsOnNonNamedTypeReturnType() {
+ $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectUnionReturnType::equalsUnionReturnType() does not declare bool return type.';
+
+ $exception = self::COMPARATOR_EXCEPTION;
+ if ( \class_exists( ComparisonMethodDoesNotDeclareBoolReturnTypeException::class ) ) {
+ // PHPUnit > 9.4.0.
+ $exception = ComparisonMethodDoesNotDeclareBoolReturnTypeException::class;
+ }
+
+ $this->expectException( $exception );
+ $this->expectExceptionMessage( $msg );
+
+ $expected = new ValueObjectUnionReturnType( 100 );
+ $actual = new ValueObjectUnionReturnType( 100 );
+ $this->assertObjectEquals( $expected, $actual, 'equalsUnionReturnType' );
+ }
+
+ /**
+ * Verify that the assertObjectEquals() method throws an error when the declared return type is nullable.
+ *
+ * @requires PHP 7.1
+ *
+ * @return void
+ */
+ #[RequiresPhp( '7.1' )]
+ public function testAssertObjectEqualsFailsOnNullableReturnType() {
+ $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObjectNullableReturnType::equalsNullableReturnType() does not declare bool return type.';
+
+ $exception = self::COMPARATOR_EXCEPTION;
+ if ( \class_exists( ComparisonMethodDoesNotDeclareBoolReturnTypeException::class ) ) {
+ // PHPUnit > 9.4.0.
+ $exception = ComparisonMethodDoesNotDeclareBoolReturnTypeException::class;
+ }
+
+ $this->expectException( $exception );
+ $this->expectExceptionMessage( $msg );
+
+ $expected = new ValueObjectNullableReturnType( 100 );
+ $actual = new ValueObjectNullableReturnType( 100 );
+ $this->assertObjectEquals( $expected, $actual, 'equalsNullableReturnType' );
+ }
+
+ /**
+ * Verify that the assertObjectEquals() method throws an error when the declared return type is not boolean.
+ *
+ * @return void
+ */
+ public function testAssertObjectEqualsFailsOnNonBooleanReturnType() {
+ $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObject::equalsNonBooleanReturnType() does not declare bool return type.';
+
+ $exception = self::COMPARATOR_EXCEPTION;
+ if ( \class_exists( ComparisonMethodDoesNotDeclareBoolReturnTypeException::class ) ) {
+ // PHPUnit > 9.4.0.
+ $exception = ComparisonMethodDoesNotDeclareBoolReturnTypeException::class;
+ }
+
+ $this->expectException( $exception );
+ $this->expectExceptionMessage( $msg );
+
+ $expected = new ValueObject( 100 );
+ $actual = new ValueObject( 100 );
+ $this->assertObjectEquals( $expected, $actual, 'equalsNonBooleanReturnType' );
+ }
+
/**
* Verify that the assertObjectEquals() method throws an error when the $method accepts more than one parameter.
*
@@ -355,30 +443,6 @@ public function testAssertObjectEqualsFailsOnMethodParamTypeMismatch() {
$this->assertObjectEquals( new stdClass(), $actual );
}
- /**
- * Verify that the assertObjectEquals() method throws an error when the declared return type/
- * the return value is not boolean.
- *
- * @return void
- */
- public function testAssertObjectEqualsFailsOnNonBooleanReturnValue() {
- $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObject::equalsNonBooleanReturnType() does not return a boolean value.';
-
- $exception = self::COMPARATOR_EXCEPTION;
- if ( \class_exists( ComparisonMethodDoesNotDeclareBoolReturnTypeException::class ) ) {
- // PHPUnit > 9.4.0.
- $msg = 'Comparison method Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObject::equalsNonBooleanReturnType() does not declare bool return type.';
- $exception = ComparisonMethodDoesNotDeclareBoolReturnTypeException::class;
- }
-
- $this->expectException( $exception );
- $this->expectExceptionMessage( $msg );
-
- $expected = new ValueObject( 100 );
- $actual = new ValueObject( 100 );
- $this->assertObjectEquals( $expected, $actual, 'equalsNonBooleanReturnType' );
- }
-
/**
* Verify that the assertObjectEquals() method fails a test when a call to method
* determines that the objects are not equal.
diff --git a/tests/Polyfills/AssertObjectPropertyTest.php b/tests/Polyfills/AssertObjectPropertyTest.php
index 8ccc2f0..16c31b6 100644
--- a/tests/Polyfills/AssertObjectPropertyTest.php
+++ b/tests/Polyfills/AssertObjectPropertyTest.php
@@ -61,7 +61,7 @@ public function testAssertObjectHasPropertyFailsOnInvalidInputTypePropertyName(
$this->expectExceptionMessage( $msg );
}
else {
- // PHP 5/7.
+ // PHP 7.
$pattern = '`^Argument 1 passed to [^\s]*assertObjectHasProperty\(\) must be of (the )?type string, `';
$this->expectExceptionMessageMatches( $pattern );
}
@@ -91,7 +91,7 @@ public function testAssertObjectNotHasPropertyFailsOnInvalidInputTypePropertyNam
$this->expectExceptionMessage( $msg );
}
else {
- // PHP 5/7.
+ // PHP 7.
$pattern = '`^Argument 1 passed to [^\s]*assertObjectNotHasProperty\(\) must be of (the )?type string, `';
$this->expectExceptionMessageMatches( $pattern );
}
@@ -138,7 +138,7 @@ public function testAssertObjectHasPropertyFailsOnInvalidInputTypeObject( $input
$this->expectExceptionMessage( $msg );
}
else {
- // PHP 5/7.
+ // PHP 7.
$pattern = '`^Argument 2 passed to [^\s]*assertObjectHasProperty\(\) must be (of type|an) object, `';
$this->expectExceptionMessageMatches( $pattern );
}
@@ -164,7 +164,7 @@ public function testAssertObjectNotHasPropertyFailsOnInvalidInputTypeObject( $in
$this->expectExceptionMessage( $msg );
}
else {
- // PHP 5/7.
+ // PHP 7.
$pattern = '`^Argument 2 passed to [^\s]*assertObjectNotHasProperty\(\) must be (of type|an) object, `';
$this->expectExceptionMessageMatches( $pattern );
}
diff --git a/tests/Polyfills/Fixtures/ValueObject.php b/tests/Polyfills/Fixtures/ValueObject.php
index 777a984..7d3a013 100644
--- a/tests/Polyfills/Fixtures/ValueObject.php
+++ b/tests/Polyfills/Fixtures/ValueObject.php
@@ -47,6 +47,28 @@ public function nonDefaultName( ValueObject $other ): bool {
return ( $this->value === $other->value );
}
+ /**
+ * Comparator method: incorrectly declared - missing return type.
+ *
+ * @param self $other Object to compare.
+ *
+ * @return bool
+ */
+ public function equalsMissingReturnType( self $other ) {
+ return ( $this->value === $other->value );
+ }
+
+ /**
+ * Comparator method: incorrectly declared - non-boolean return type/value.
+ *
+ * @param self $other Object to compare.
+ *
+ * @return bool
+ */
+ public function equalsNonBooleanReturnType( self $other ): int {
+ return ( $this->value <=> $other->value );
+ }
+
/**
* Comparator method: incorrectly declared - more than one parameter.
*
@@ -91,15 +113,4 @@ public function equalsParamNonClassType( array $other ): bool {
public function equalsParamNonExistentClassType( ClassWhichDoesntExist $other ): bool {
return ( $this->value === $other->value );
}
-
- /**
- * Comparator method: incorrectly declared - non-boolean return type/value.
- *
- * @param self $other Object to compare.
- *
- * @return bool
- */
- public function equalsNonBooleanReturnType( self $other ): int {
- return ( $this->value <=> $other->value );
- }
}
diff --git a/tests/Polyfills/Fixtures/ValueObjectNoReturnType.php b/tests/Polyfills/Fixtures/ValueObjectNoReturnType.php
deleted file mode 100644
index 913611d..0000000
--- a/tests/Polyfills/Fixtures/ValueObjectNoReturnType.php
+++ /dev/null
@@ -1,124 +0,0 @@
-value = $value;
- }
-
- /**
- * Comparator method: correctly declared.
- *
- * @param ValueObjectNoReturnType $other Object to compare.
- *
- * @return bool
- */
- public function equals( ValueObjectNoReturnType $other ) {
- return ( $this->value === $other->value );
- }
-
- /**
- * Comparator method: correctly declared and with self as type instead of the class name.
- *
- * @param self $other Object to compare.
- *
- * @return bool
- */
- public function nonDefaultName( self $other ) {
- return ( $this->value === $other->value );
- }
-
- /**
- * Comparator method: incorrectly declared - more than one parameter.
- *
- * @param ValueObjectNoReturnType $other Object to compare.
- * @param mixed $param Just testing.
- *
- * @return bool
- */
- public function equalsTwoParams( $other, $param ) {
- return ( $param && $this->value === $other->value );
- }
-
- /**
- * Comparator method: incorrectly declared - parameter is not required.
- *
- * @param self|null $other Object to compare.
- *
- * @return bool
- */
- public function equalsParamNotRequired( self $other = null ) {
- return ( $this->value === $other->value );
- }
-
- /**
- * Comparator method: incorrectly declared - parameter is not typed.
- *
- * @param ValueObjectNoReturnType $other Object to compare.
- *
- * @return bool
- */
- public function equalsParamNoType( $other ) {
- return ( $this->value === $other->value );
- }
-
- /**
- * Comparator method: incorrectly declared - parameter has a non-classname type.
- *
- * @param array $other Object to compare.
- *
- * @return bool
- */
- public function equalsParamNonClassType( array $other ) {
- return ( $this->value === $other->value );
- }
-
- /**
- * Comparator method: incorrectly declared - parameter has a non-existent classname type.
- *
- * @param ClassWhichDoesntExist $other Object to compare.
- *
- * @return bool
- */
- public function equalsParamNonExistentClassType( ClassWhichDoesntExist $other ) {
- return ( $this->value === $other->value );
- }
-
- /**
- * Comparator method: incorrectly declared - non-boolean return type/value.
- *
- * @param self $other Object to compare.
- *
- * @return int
- */
- public function equalsNonBooleanReturnType( self $other ) {
- if ( $this->value === $other->value ) {
- return 0;
- }
-
- if ( $this->value > $other->value ) {
- return 1;
- }
-
- return -1;
- }
-}
diff --git a/tests/Polyfills/Fixtures/ValueObjectNullableReturnType.php b/tests/Polyfills/Fixtures/ValueObjectNullableReturnType.php
new file mode 100644
index 0000000..45c98af
--- /dev/null
+++ b/tests/Polyfills/Fixtures/ValueObjectNullableReturnType.php
@@ -0,0 +1,39 @@
+value = $value;
+ }
+
+ /**
+ * Comparator method: incorrectly declared - return type is nullable.
+ *
+ * @param self $other Object to compare.
+ *
+ * @return bool
+ */
+ public function equalsNullableReturnType( self $other ): ?bool {
+ return ( $this->value === $other->value );
+ }
+}
diff --git a/tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php b/tests/Polyfills/Fixtures/ValueObjectUnionReturnType.php
similarity index 55%
rename from tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php
rename to tests/Polyfills/Fixtures/ValueObjectUnionReturnType.php
index efa2387..d937600 100644
--- a/tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php
+++ b/tests/Polyfills/Fixtures/ValueObjectUnionReturnType.php
@@ -4,8 +4,11 @@
/**
* Fixture to test the AssertObjectEquals trait.
+ *
+ * This `equals*()` method needs to be in this separate fixture as it needs
+ * a union type declaration (PHP 8.0+).
*/
-class ValueObjectUnionNoReturnType {
+class ValueObjectUnionReturnType {
/**
* The value.
@@ -24,13 +27,13 @@ public function __construct( $value ) {
}
/**
- * Comparator method: incorrectly declared - parameter has a union type.
+ * Comparator method: incorrectly declared - union type as return type.
*
- * @param self|OtherClass|array $other Object to compare.
+ * @param self $other Object to compare.
*
* @return bool
*/
- public function equalsParamUnionType( self|OtherClass|array $other ) {
+ public function equalsUnionReturnType( self $other ): bool|int {
return ( $this->value === $other->value );
}
}
diff --git a/tests/TestCases/TestCaseTestTrait.php b/tests/TestCases/TestCaseTestTrait.php
index b41c8be..ae9a67b 100644
--- a/tests/TestCases/TestCaseTestTrait.php
+++ b/tests/TestCases/TestCaseTestTrait.php
@@ -3,7 +3,6 @@
namespace Yoast\PHPUnitPolyfills\Tests\TestCases;
use Exception;
-use PHPUnit\Framework\Attributes\RequiresPhp;
use stdClass;
use Yoast\PHPUnitPolyfills\Tests\Polyfills\AssertFileEqualsSpecializationsTest;
use Yoast\PHPUnitPolyfills\Tests\Polyfills\Fixtures\ValueObject;
@@ -126,11 +125,8 @@ final public function testAvailabilityEqualToSpecializations() {
/**
* Verify availability of trait polyfilled PHPUnit methods [14].
*
- * @requires PHP 7.0
- *
* @return void
*/
- #[RequiresPhp( '7.0' )]
final public function testAvailabilityAssertObjectEquals() {
$expected = new ValueObject( 'test' );
$actual = new ValueObject( 'test' );