Skip to content

Commit

Permalink
Merge pull request #198 from Yoast/feature/3.x/new-assertarraywithlis…
Browse files Browse the repository at this point in the history
…tkeys-polyfill-trait

PHPUnit 11 | AssertArrayWithListKeys trait: polyfill the Assert::assertArrayIsEqualToArrayOnlyConsideringListOfKeys() et al methods
  • Loading branch information
hellofromtonya authored Sep 6, 2024
2 parents 5aa0561 + 3189123 commit 9ffaffb
Show file tree
Hide file tree
Showing 9 changed files with 681 additions and 0 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,25 @@ These methods were later backported to the PHPUnit 9 branch and included in the
[`Assert::assertObjectHasProperty()`]: https://docs.phpunit.de/en/main/assertions.html#assertObjectHasProperty
[`Assert::assertObjectNotHasProperty()`]: https://docs.phpunit.de/en/main/assertions.html#assertObjectHasProperty

#### PHPUnit < 11.0.0: `Yoast\PHPUnitPolyfills\Polyfills\AssertArrayWithListKeys`

Polyfills the following method:
| | |
| -------------------------------------------------------------------- | ------------------------------------------------------------- |
| [`Assert::assertArrayIsEqualToArrayOnlyConsideringListOfKeys()`] | [`Assert::assertArrayIsEqualToArrayIgnoringListOfKeys()`] |
| [`Assert::assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys()`] | [`Assert::assertArrayIsIdenticalToArrayIgnoringListOfKeys()`] |

These methods were introduced in PHPUnit 11.0.0.

This functionality resembles the functionality previously offered by the `Assert::assertArraySubset()` assertion, which was removed in PHPUnit 9.0.0, but with higher precision.

Refactoring tests which still use `Assert::assertArraySubset()` to use the new assertions should be considered as an upgrade path.

[`Assert::assertArrayIsEqualToArrayOnlyConsideringListOfKeys()`]: https://docs.phpunit.de/en/main/assertions.html#assertarrayisequaltoarrayonlyconsideringlistofkeys
[`Assert::assertArrayIsEqualToArrayIgnoringListOfKeys()`]: https://docs.phpunit.de/en/main/assertions.html#assertarrayisequaltoarrayignoringlistofkeys
[`Assert::assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys()`]: https://docs.phpunit.de/en/main/assertions.html#assertarrayisidenticaltoarrayonlyconsideringlistofkeys
[`Assert::assertArrayIsIdenticalToArrayIgnoringListOfKeys()`]: https://docs.phpunit.de/en/main/assertions.html#assertarrayisidenticaltoarrayignoringlistofkeys


### TestCases

Expand Down
21 changes: 21 additions & 0 deletions phpunitpolyfills-autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ public static function load( $className ) {
self::loadAssertObjectProperty();
return true;

case 'Yoast\PHPUnitPolyfills\Polyfills\AssertArrayWithListKeys':
self::loadAssertArrayWithListKeys();
return true;

case 'Yoast\PHPUnitPolyfills\TestCases\TestCase':
self::loadTestCase();
return true;
Expand Down Expand Up @@ -313,6 +317,23 @@ public static function loadAssertObjectProperty() {
require_once __DIR__ . '/src/Polyfills/AssertObjectProperty_Empty.php';
}

/**
* Load the AssertArrayWithListKeys 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 loadAssertArrayWithListKeys() {
if ( \method_exists( Assert::class, 'assertArrayIsEqualToArrayOnlyConsideringListOfKeys' ) === false ) {
// PHPUnit < 11.0.0.
require_once __DIR__ . '/src/Polyfills/AssertArrayWithListKeys.php';
return;
}

// PHPUnit >= 11.0.0.
require_once __DIR__ . '/src/Polyfills/AssertArrayWithListKeys_Empty.php';
}

/**
* Load the appropriate TestCase class based on the PHPUnit version being used.
*
Expand Down
120 changes: 120 additions & 0 deletions src/Polyfills/AssertArrayWithListKeys.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

namespace Yoast\PHPUnitPolyfills\Polyfills;

/**
* Polyfill the Assert::assertArrayIsEqualToArrayOnlyConsideringListOfKeys(),
* Assert::assertArrayIsEqualToArrayIgnoringListOfKeys(),
* Assert::assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys(),
* and Assert::assertArrayIsIdenticalToArrayIgnoringListOfKeys() methods.
*
* Introduced in PHPUnit 11.0.0.
*
* This functionality resembles the functionality previously offered by the `Assert::assertArraySubset()`
* assertion, which was removed in PHPUnit 9.0.0, but with higher precision.
*
* Refactoring tests which still use `Assert::assertArraySubset()` to use the new assertions should be
* considered as an upgrade path.
*
* @link https://github.com/sebastianbergmann/phpunit/pull/5600
* @link https://github.com/sebastianbergmann/phpunit/pull/5716 Included in PHPUnit 11.0.4.
* @link https://github.com/sebastianbergmann/phpunit/pull/5729 Included in PHPUnit 11.0.6.
*
* @since 3.0.0
*/
trait AssertArrayWithListKeys {

/**
* Asserts that two arrays are equal while only considering array elements for which the keys have been specified.
*
* {@internal As the array type declarations don't lead to type juggling, even without strict_types,
* it is safe to let PHP handle the parameter validation.}
*
* @param array<mixed> $expected Expected value.
* @param array<mixed> $actual The variable to test.
* @param array<int|string> $keysToBeConsidered The array keys to take into account.
* @param string $message Optional failure message to display.
*
* @return void
*/
final public static function assertArrayIsEqualToArrayOnlyConsideringListOfKeys( array $expected, array $actual, array $keysToBeConsidered, string $message = '' ) {
$filteredExpected = [];
foreach ( $keysToBeConsidered as $key ) {
if ( isset( $expected[ $key ] ) ) {
$filteredExpected[ $key ] = $expected[ $key ];
}
}

$filteredActual = [];
foreach ( $keysToBeConsidered as $key ) {
if ( isset( $actual[ $key ] ) ) {
$filteredActual[ $key ] = $actual[ $key ];
}
}

static::assertEquals( $filteredExpected, $filteredActual, $message );
}

/**
* Asserts that two arrays are equal while ignoring array elements for which the keys have been specified.
*
* {@internal As the array type declarations don't lead to type juggling, even without strict_types,
* it is safe to let PHP handle the parameter validation.}
*
* @param array<mixed> $expected Expected value.
* @param array<mixed> $actual The variable to test.
* @param array<int|string> $keysToBeIgnored The array keys to ignore.
* @param string $message Optional failure message to display.
*
* @return void
*/
final public static function assertArrayIsEqualToArrayIgnoringListOfKeys( array $expected, array $actual, array $keysToBeIgnored, string $message = '' ) {
foreach ( $keysToBeIgnored as $key ) {
unset( $expected[ $key ], $actual[ $key ] );
}

static::assertEquals( $expected, $actual, $message );
}

/**
* Asserts that two arrays are identical while only considering array elements for which the keys have been specified.
*
* {@internal As the array type declarations don't lead to type juggling, even without strict_types,
* it is safe to let PHP handle the parameter validation.}
*
* @param array<mixed> $expected Expected value.
* @param array<mixed> $actual The variable to test.
* @param array<int|string> $keysToBeConsidered The array keys to take into account.
* @param string $message Optional failure message to display.
*
* @return void
*/
final public static function assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys( array $expected, array $actual, array $keysToBeConsidered, string $message = '' ) {
$keysToBeConsidered = \array_combine( $keysToBeConsidered, $keysToBeConsidered );
$expected = \array_intersect_key( $expected, $keysToBeConsidered );
$actual = \array_intersect_key( $actual, $keysToBeConsidered );

static::assertSame( $expected, $actual, $message );
}

/**
* Asserts that two arrays are identical while ignoring array elements for which the keys have been specified.
*
* {@internal As the array type declarations don't lead to type juggling, even without strict_types,
* it is safe to let PHP handle the parameter validation.}
*
* @param array<mixed> $expected Expected value.
* @param array<mixed> $actual The variable to test.
* @param array<int|string> $keysToBeIgnored The array keys to ignore.
* @param string $message Optional failure message to display.
*
* @return void
*/
final public static function assertArrayIsIdenticalToArrayIgnoringListOfKeys( array $expected, array $actual, array $keysToBeIgnored, string $message = '' ) {
foreach ( $keysToBeIgnored as $key ) {
unset( $expected[ $key ], $actual[ $key ] );
}

static::assertSame( $expected, $actual, $message );
}
}
8 changes: 8 additions & 0 deletions src/Polyfills/AssertArrayWithListKeys_Empty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Yoast\PHPUnitPolyfills\Polyfills;

/**
* Empty trait for use with PHPUnit >= 11.0.0 in which the polyfill is not needed.
*/
trait AssertArrayWithListKeys {}
2 changes: 2 additions & 0 deletions src/TestCases/TestCasePHPUnitGte8.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Yoast\PHPUnitPolyfills\TestCases;

use PHPUnit\Framework\TestCase as PHPUnit_TestCase;
use Yoast\PHPUnitPolyfills\Polyfills\AssertArrayWithListKeys;
use Yoast\PHPUnitPolyfills\Polyfills\AssertClosedResource;
use Yoast\PHPUnitPolyfills\Polyfills\AssertFileEqualsSpecializations;
use Yoast\PHPUnitPolyfills\Polyfills\AssertIgnoringLineEndings;
Expand All @@ -24,6 +25,7 @@
*/
abstract class TestCase extends PHPUnit_TestCase {

use AssertArrayWithListKeys;
use AssertClosedResource;
use AssertFileEqualsSpecializations;
use AssertIgnoringLineEndings;
Expand Down
2 changes: 2 additions & 0 deletions src/TestCases/TestCasePHPUnitLte7.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Yoast\PHPUnitPolyfills\TestCases;

use PHPUnit\Framework\TestCase as PHPUnit_TestCase;
use Yoast\PHPUnitPolyfills\Polyfills\AssertArrayWithListKeys;
use Yoast\PHPUnitPolyfills\Polyfills\AssertClosedResource;
use Yoast\PHPUnitPolyfills\Polyfills\AssertEqualsSpecializations;
use Yoast\PHPUnitPolyfills\Polyfills\AssertFileEqualsSpecializations;
Expand All @@ -27,6 +28,7 @@
*/
abstract class TestCase extends PHPUnit_TestCase {

use AssertArrayWithListKeys;
use AssertClosedResource;
use AssertEqualsSpecializations;
use AssertFileEqualsSpecializations;
Expand Down
2 changes: 2 additions & 0 deletions src/TestCases/XTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPUnit\Framework\Attributes\Before;
use PHPUnit\Framework\Attributes\BeforeClass;
use PHPUnit\Framework\TestCase as PHPUnit_TestCase;
use Yoast\PHPUnitPolyfills\Polyfills\AssertArrayWithListKeys;
use Yoast\PHPUnitPolyfills\Polyfills\AssertClosedResource;
use Yoast\PHPUnitPolyfills\Polyfills\AssertEqualsSpecializations;
use Yoast\PHPUnitPolyfills\Polyfills\AssertFileEqualsSpecializations;
Expand All @@ -33,6 +34,7 @@
*/
abstract class XTestCase extends PHPUnit_TestCase {

use AssertArrayWithListKeys;
use AssertClosedResource;
use AssertEqualsSpecializations;
use AssertFileEqualsSpecializations;
Expand Down
Loading

0 comments on commit 9ffaffb

Please sign in to comment.