Merge pull request #517 from fgaroby/make_toHaveKeys_accepts_multi-dimensional_arrays

Make 'toHaveKeys' accept multi-dimensional associative arrays
This commit is contained in:
Luke Downing
2022-05-06 15:29:30 +02:00
committed by GitHub
4 changed files with 49 additions and 6 deletions

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Pest\Expectations;
use Pest\Expectation;
use Pest\Support\Arr;
use PHPUnit\Framework\ExpectationFailedException;
use SebastianBergmann\Exporter\Exporter;
@ -29,15 +30,19 @@ final class OppositeExpectation
/**
* Asserts that the value array not has the provided $keys.
*
* @param array<int, int|string> $keys
* @param array<int, int|string|array<int-string, mixed>> $keys
*
* @return Expectation<TValue>
*/
public function toHaveKeys(array $keys): Expectation
{
foreach ($keys as $key) {
foreach ($keys as $k => $key) {
try {
if (is_array($key)) {
$this->toHaveKeys(array_keys(Arr::dot($key, $k . '.')));
} else {
$this->original->toHaveKey($key);
}
} catch (ExpectationFailedException) {
continue;
}

View File

@ -595,15 +595,19 @@ final class Expectation
/**
* Asserts that the value array has the provided $keys.
*
* @param array<int, int|string> $keys
* @param array<int, int|string|array<int-string, mixed>> $keys
*
* @return Expectation<TValue>
*/
public function toHaveKeys(array $keys): Expectation
{
foreach ($keys as $key) {
foreach ($keys as $k => $key) {
if (is_array($key)) {
$this->toHaveKeys(array_keys(Arr::dot($key, $k . '.')));
} else {
$this->toHaveKey($key);
}
}
return $this;
}

View File

@ -60,4 +60,26 @@ final class Arr
return $array;
}
/**
* Flatten a multi-dimensional associative array with dots.
*
* @param array<array-key, mixed> $array
*
* @return array<int|string, mixed>
*/
public static function dot(array $array, string $prepend = ''): array
{
$results = [];
foreach ($array as $key => $value) {
if (is_array($value) && count($value) > 0) {
$results = array_merge($results, static::dot($value, $prepend . $key . '.'));
} else {
$results[$prepend . $value] = $value;
}
}
return $results;
}
}

View File

@ -6,10 +6,22 @@ test('pass', function () {
expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => 'baz']])->toHaveKeys(['a', 'c', 'foo.bar']);
});
test('pass with multi-dimensional arrays', function () {
expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => ['bir' => 'biz']]])->toHaveKeys(['a', 'c', 'foo' => ['bar' => ['bir']]]);
});
test('failures', function () {
expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => 'baz']])->toHaveKeys(['a', 'd', 'foo.bar', 'hello.world']);
})->throws(ExpectationFailedException::class);
test('failures with multi-dimensional arrays', function () {
expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => ['bir' => 'biz']]])->toHaveKeys(['a', 'd', 'foo' => ['bar' => 'bir'], 'hello.world']);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => 'baz']])->not->toHaveKeys(['foo.bar', 'c', 'z']);
})->throws(ExpectationFailedException::class);
test('not failures with multi-dimensional arrays', function () {
expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => ['bir' => 'biz']]])->not->toHaveKeys(['foo' => ['bar' => 'bir'], 'c', 'z']);
})->throws(ExpectationFailedException::class);