From 096f7fffd86321604eb648de9735d2787fefea93 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish <42181698+cosmastech@users.noreply.github.com> Date: Sun, 14 May 2023 08:09:13 -0400 Subject: [PATCH] allows passing an `enum` to `randomElement()` or `randomElements()` (#620) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * allows passing an enum to randomElement or randomElements * psalm fix * fix: array not an instanceof Traversable * specify class-string * Update test/Faker/Provider/BaseTest.php Co-authored-by: Andreas Möller * remove require_once Co-authored-by: Andreas Möller * clean up tests splits tests, splits phases of tests, adds more specific assertions Co-authored-by: Andreas Möller * Apply suggestions from code review Co-authored-by: Andreas Möller * Fix: Avoid unnecessary import * Fix: Remove unnecessary reference to root namespace * Fix: Exclude BackedEnum * Fix: DocBlock * Fix: Run 'make baseline' * Fix: Run 'make baseline' * Fix: Test --------- Co-authored-by: Andreas Möller --- .php-cs-fixer.dist.php | 3 +++ phpstan-baseline.neon | 5 +++++ psalm.baseline.xml | 8 ++++++++ src/Faker/Provider/Base.php | 22 ++++++++++++++++------ test/Faker/Provider/BaseTest.php | 30 ++++++++++++++++++++++++++++-- test/Fixture/Enum/BackedEnum.php | 12 ++++++++++++ 6 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 test/Fixture/Enum/BackedEnum.php diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 847b3c6c48..ff9a013169 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -8,6 +8,9 @@ '.github/', 'vendor-bin/', ]) + ->notPath([ + 'test/Fixture/Enum/BackedEnum.php', + ]) ->ignoreDotFiles(false) ->in(__DIR__); diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index d0ef6d35f6..a9b8f8536c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -610,6 +610,11 @@ parameters: count: 1 path: src/Faker/ORM/Spot/Populator.php + - + message: "#^Class UnitEnum not found\\.$#" + count: 2 + path: src/Faker/Provider/Base.php + - message: """ #^Instantiation of deprecated class Faker\\\\DefaultGenerator\\: diff --git a/psalm.baseline.xml b/psalm.baseline.xml index 1c9b9ada28..277230f16a 100644 --- a/psalm.baseline.xml +++ b/psalm.baseline.xml @@ -142,9 +142,17 @@ [static::class, 'randomDigit'] + + \UnitEnum + \UnitEnum + Closure + + enum_exists($array) + enum_exists($array) + diff --git a/src/Faker/Provider/Base.php b/src/Faker/Provider/Base.php index d48b57d5d6..675cf89e76 100644 --- a/src/Faker/Provider/Base.php +++ b/src/Faker/Provider/Base.php @@ -179,9 +179,9 @@ public static function randomAscii() /** * Returns randomly ordered subsequence of $count elements from a provided array * - * @param array|\Traversable $array Array to take elements from. Defaults to a-c - * @param int $count Number of elements to take. - * @param bool $allowDuplicates Allow elements to be picked several times. Defaults to false + * @param array|class-string|\Traversable $array Array to take elements from. Defaults to a-c + * @param int $count Number of elements to take. + * @param bool $allowDuplicates Allow elements to be picked several times. Defaults to false * * @throws \InvalidArgumentException * @throws \LengthException When requesting more elements than provided @@ -192,13 +192,18 @@ public static function randomElements($array = ['a', 'b', 'c'], $count = 1, $all { $elements = $array; + if (is_string($array) && function_exists('enum_exists') && enum_exists($array)) { + $elements = $array::cases(); + } + if ($array instanceof \Traversable) { $elements = \iterator_to_array($array, false); } if (!is_array($elements)) { throw new \InvalidArgumentException(sprintf( - 'Argument for parameter $array needs to be array or an instance of %s, got %s instead.', + 'Argument for parameter $array needs to be array, an instance of %s, or an instance of %s, got %s instead.', + \UnitEnum::class, \Traversable::class, is_object($array) ? get_class($array) : gettype($array), )); @@ -245,7 +250,7 @@ public static function randomElements($array = ['a', 'b', 'c'], $count = 1, $all /** * Returns a random element from a passed array * - * @param array|\Traversable $array + * @param array|class-string|\Traversable $array * * @throws \InvalidArgumentException */ @@ -253,6 +258,10 @@ public static function randomElement($array = ['a', 'b', 'c']) { $elements = $array; + if (is_string($array) && function_exists('enum_exists') && enum_exists($array)) { + $elements = $array::cases(); + } + if ($array instanceof \Traversable) { $elements = iterator_to_array($array, false); } @@ -263,7 +272,8 @@ public static function randomElement($array = ['a', 'b', 'c']) if (!is_array($elements)) { throw new \InvalidArgumentException(sprintf( - 'Argument for parameter $array needs to be array or an instance of %s, got %s instead.', + 'Argument for parameter $array needs to be array, an instance of %s, or an instance of %s, got %s instead.', + \UnitEnum::class, \Traversable::class, is_object($array) ? get_class($array) : gettype($array), )); diff --git a/test/Faker/Provider/BaseTest.php b/test/Faker/Provider/BaseTest.php index f1a1d61808..bb64857f8a 100644 --- a/test/Faker/Provider/BaseTest.php +++ b/test/Faker/Provider/BaseTest.php @@ -3,6 +3,7 @@ namespace Faker\Test\Provider; use Faker\Provider\Base as BaseProvider; +use Faker\Test\Fixture; use Faker\Test\TestCase; /** @@ -552,7 +553,8 @@ public function testRandomElementsRejectsInvalidArgument(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage(sprintf( - 'Argument for parameter $array needs to be array or an instance of %s, got %s instead.', + 'Argument for parameter $array needs to be array, an instance of %s, or an instance of %s, got %s instead.', + \UnitEnum::class, \Traversable::class, \stdClass::class, )); @@ -564,7 +566,8 @@ public function testRandomElementRejectsInvalidArgument(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage(sprintf( - 'Argument for parameter $array needs to be array or an instance of %s, got %s instead.', + 'Argument for parameter $array needs to be array, an instance of %s, or an instance of %s, got %s instead.', + \UnitEnum::class, \Traversable::class, 'string', )); @@ -609,6 +612,29 @@ public function testRandomElementsWorksWithAllowDuplicates(): void self::assertCount(3, $randomElements); self::assertContainsOnly('string', $randomElements); } + + /** + * @requires PHP 8.1 + */ + public function testRandomElementsWithEnum(): void + { + $count = 2; + + $randomElements = BaseProvider::randomElements(Fixture\Enum\BackedEnum::class, $count); + + self::assertCount($count, $randomElements); + self::assertContainsOnlyInstancesOf(Fixture\Enum\BackedEnum::class, $randomElements); + } + + /** + * @requires PHP 8.1 + */ + public function testRandomElementWithEnum(): void + { + $randomElement = BaseProvider::randomElement(Fixture\Enum\BackedEnum::class); + + self::assertInstanceOf(Fixture\Enum\BackedEnum::class, $randomElement); + } } /** diff --git a/test/Fixture/Enum/BackedEnum.php b/test/Fixture/Enum/BackedEnum.php new file mode 100644 index 0000000000..965df23bba --- /dev/null +++ b/test/Fixture/Enum/BackedEnum.php @@ -0,0 +1,12 @@ +