From 36130eb7a0ba97b6d2710fbabc101525c34481ca Mon Sep 17 00:00:00 2001 From: Fabio Ivona Date: Fri, 18 Feb 2022 16:40:17 +0100 Subject: [PATCH 01/32] adds a failing test --- tests/Features/Expect/toThrow.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Features/Expect/toThrow.php b/tests/Features/Expect/toThrow.php index 434ced44..b5c66abf 100644 --- a/tests/Features/Expect/toThrow.php +++ b/tests/Features/Expect/toThrow.php @@ -58,3 +58,19 @@ test('closure missing parameter', function () { test('closure missing type-hint', function () { expect(function () {})->toThrow(function ($e) {}); })->throws(InvalidArgumentException::class, 'The given closure\'s parameter must be type-hinted as the class string.'); + +it('can handle a non-defined exception', function () { + expect(function () { + throw new NonExistingException(); + })->toThrow(NonExistingException::class); +})->throws(Error::class, 'Class "NonExistingException" not found'); + +it('can handle a class not found Error', function () { + expect(function () { + throw new NonExistingException(); + })->toThrow('Class "NonExistingException" not found'); + + expect(function () { + throw new NonExistingException(); + })->toThrow(Error::class, 'Class "NonExistingException" not found'); +}); From 10b204e19d0f6721e3e2ca3c4a46bfbd7e0c4547 Mon Sep 17 00:00:00 2001 From: Fabio Ivona Date: Fri, 18 Feb 2022 16:40:31 +0100 Subject: [PATCH 02/32] handles toThrow exception with a "class not found" error --- src/Mixins/Expectation.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Mixins/Expectation.php b/src/Mixins/Expectation.php index 3fbd2110..64235cfc 100644 --- a/src/Mixins/Expectation.php +++ b/src/Mixins/Expectation.php @@ -6,6 +6,7 @@ namespace Pest\Mixins; use BadMethodCallException; use Closure; +use Error; use InvalidArgumentException; use Pest\Exceptions\InvalidExpectationValue; use Pest\Support\Arr; @@ -824,6 +825,10 @@ final class Expectation ($this->value)(); } catch (Throwable $e) { // @phpstan-ignore-line if (!class_exists($exception)) { + if ($e instanceof Error && $e->getMessage() === "Class \"$exception\" not found") { + throw $e; + } + Assert::assertStringContainsString($exception, $e->getMessage()); return $this; From 2c3a2960406367c4438a51fd531dd4d5c7dcc329 Mon Sep 17 00:00:00 2001 From: Fabio Ivona Date: Fri, 18 Feb 2022 16:42:34 +0100 Subject: [PATCH 03/32] fix types --- src/Mixins/Expectation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mixins/Expectation.php b/src/Mixins/Expectation.php index 64235cfc..5823d61c 100644 --- a/src/Mixins/Expectation.php +++ b/src/Mixins/Expectation.php @@ -823,7 +823,7 @@ final class Expectation try { ($this->value)(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { if (!class_exists($exception)) { if ($e instanceof Error && $e->getMessage() === "Class \"$exception\" not found") { throw $e; From 22030bffd06eedb83cdfedd7426b9c8875adfae0 Mon Sep 17 00:00:00 2001 From: Owen Voke Date: Thu, 3 Mar 2022 16:01:09 +0000 Subject: [PATCH 04/32] ci: update to use ANSI output --- .github/workflows/static.yml | 8 ++++---- .github/workflows/tests.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 09e0d064..fc8eb823 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -20,10 +20,10 @@ jobs: coverage: none - name: Install Dependencies - run: composer update --no-interaction --no-progress + run: composer update --no-interaction --no-progress --ansi - name: Run PHP-CS-Fixer - run: PHP_CS_FIXER_IGNORE_ENV=true vendor/bin/php-cs-fixer fix -v --allow-risky=yes --dry-run + run: PHP_CS_FIXER_IGNORE_ENV=true vendor/bin/php-cs-fixer fix -v --allow-risky=yes --dry-run --ansi phpstan: runs-on: ubuntu-latest @@ -45,7 +45,7 @@ jobs: coverage: none - name: Install Dependencies - run: composer update --prefer-stable --no-interaction --no-progress + run: composer update --prefer-stable --no-interaction --no-progress --ansi - name: Run PHPStan - run: vendor/bin/phpstan analyse --no-progress --debug + run: vendor/bin/phpstan analyse --no-progress --debug --ansi diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9245e846..38eb41d1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -36,7 +36,7 @@ jobs: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - name: Install PHP dependencies - run: composer update --${{ matrix.dependency-version }} --no-interaction --no-progress + run: composer update --${{ matrix.dependency-version }} --no-interaction --no-progress --ansi - name: Unit Tests run: php bin/pest --colors=always --exclude-group=integration From 51ec80f11f1072d45f9820894d74f22afb81ef5b Mon Sep 17 00:00:00 2001 From: Owen Voke Date: Thu, 3 Mar 2022 18:20:24 +0000 Subject: [PATCH 05/32] fix: resolve PHPStan warnings --- src/Bootstrappers/BootFiles.php | 1 + src/Expectation.php | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bootstrappers/BootFiles.php b/src/Bootstrappers/BootFiles.php index 51781ff2..5817c3a8 100644 --- a/src/Bootstrappers/BootFiles.php +++ b/src/Bootstrappers/BootFiles.php @@ -48,6 +48,7 @@ final class BootFiles if (is_dir($filename)) { $directory = new RecursiveDirectoryIterator($filename); $iterator = new RecursiveIteratorIterator($directory); + /** @var \DirectoryIterator $file */ foreach ($iterator as $file) { $this->load($file->__toString()); } diff --git a/src/Expectation.php b/src/Expectation.php index 191d762e..7703ebb8 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -151,7 +151,6 @@ final class Expectation throw new BadMethodCallException('Expectation value is not iterable.'); } - //@phpstan-ignore-next-line $value = is_array($this->value) ? $this->value : iterator_to_array($this->value); $keys = array_keys($value); $values = array_values($value); From 0e85921964dcdcbbf599f96f0fc4a8570c3edcb1 Mon Sep 17 00:00:00 2001 From: Kohei Matsumoto Date: Fri, 4 Mar 2022 13:05:55 +0900 Subject: [PATCH 06/32] feat: Add code to the throws arg --- src/PendingCalls/TestCall.php | 16 ++++++++++++---- tests/Features/Exceptions.php | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index 0d1cd17c..b2266879 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -45,9 +45,11 @@ final class TestCall /** * Asserts that the test throws the given `$exceptionClass` when called. */ - public function throws(string $exception, string $exceptionMessage = null): TestCall + public function throws(string|int $exception, string $exceptionMessage = null, int $exceptionCode = null): TestCall { - if (class_exists($exception)) { + if (is_int($exception)) { + $exceptionCode = $exception; + } else if (class_exists($exception)) { $this->testCaseMethod ->proxies ->add(Backtrace::file(), Backtrace::line(), 'expectException', [$exception]); @@ -61,6 +63,12 @@ final class TestCall ->add(Backtrace::file(), Backtrace::line(), 'expectExceptionMessage', [$exceptionMessage]); } + if (is_int($exceptionCode)) { + $this->testCaseMethod + ->proxies + ->add(Backtrace::file(), Backtrace::line(), 'expectExceptionCode', [$exceptionCode]); + } + return $this; } @@ -69,7 +77,7 @@ final class TestCall * * @param (callable(): bool)|bool $condition */ - public function throwsIf(callable|bool $condition, string $exception, string $exceptionMessage = null): TestCall + public function throwsIf(callable|bool $condition, string|int $exception, string $exceptionMessage = null, int $exceptionCode = null): TestCall { $condition = is_callable($condition) ? $condition @@ -78,7 +86,7 @@ final class TestCall }; if ($condition()) { - return $this->throws($exception, $exceptionMessage); + return $this->throws($exception, $exceptionMessage, $exceptionCode); } return $this; diff --git a/tests/Features/Exceptions.php b/tests/Features/Exceptions.php index 9970c2a9..71482fbe 100644 --- a/tests/Features/Exceptions.php +++ b/tests/Features/Exceptions.php @@ -14,10 +14,18 @@ it('catch exceptions and messages', function () { throw new Exception('Something bad happened'); })->throws(Exception::class, 'Something bad happened'); +it('catch exceptions, messages and code', function () { + throw new Exception('Something bad happened', 1); +})->throws(Exception::class, 'Something bad happened', 1); + it('can just define the message', function () { throw new Exception('Something bad happened'); })->throws('Something bad happened'); +it('can just define the code', function () { + throw new Exception('Something bad happened', 1); +})->throws(1); + it('not catch exceptions if given condition is false', function () { $this->assertTrue(true); })->throwsIf(false, Exception::class); @@ -30,10 +38,22 @@ it('catch exceptions and messages if given condition is true', function () { throw new Exception('Something bad happened'); })->throwsIf(true, Exception::class, 'Something bad happened'); +it('catch exceptions, messages and code if given condition is true', function () { + throw new Exception('Something bad happened', 1); +})->throwsIf(true, Exception::class, 'Something bad happened', 1); + it('can just define the message if given condition is true', function () { throw new Exception('Something bad happened'); })->throwsIf(true, 'Something bad happened'); +it('can just define the code if given condition is true', function () { + throw new Exception('Something bad happened', 1); +})->throwsIf(true, 1); + it('can just define the message if given condition is 1', function () { throw new Exception('Something bad happened'); })->throwsIf(1, 'Something bad happened'); + +it('can just define the code if given condition is 1', function () { + throw new Exception('Something bad happened', 1); +})->throwsIf(1, 1); From 03ccea8978b3165f6c8455d895a9edac370b6c41 Mon Sep 17 00:00:00 2001 From: Fabio Ivona Date: Fri, 4 Mar 2022 17:36:02 +0100 Subject: [PATCH 07/32] fix code style --- src/PendingCalls/TestCall.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index b2266879..f9e786c1 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -49,7 +49,7 @@ final class TestCall { if (is_int($exception)) { $exceptionCode = $exception; - } else if (class_exists($exception)) { + } elseif (class_exists($exception)) { $this->testCaseMethod ->proxies ->add(Backtrace::file(), Backtrace::line(), 'expectException', [$exception]); From 7660517f7c4b58e6a6f128cd9a179d2a75fdcbf4 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Fri, 4 Mar 2022 22:28:37 +0100 Subject: [PATCH 08/32] start covers attribute implementation --- src/Factories/Attributes/Covers.php | 35 +++++++++++++++++++++++++ src/Factories/TestCaseMethodFactory.php | 20 +++++++++++++- src/PendingCalls/TestCall.php | 20 ++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/Factories/Attributes/Covers.php diff --git a/src/Factories/Attributes/Covers.php b/src/Factories/Attributes/Covers.php new file mode 100644 index 00000000..2c6234f3 --- /dev/null +++ b/src/Factories/Attributes/Covers.php @@ -0,0 +1,35 @@ + $attributes + * + * @return array + */ + public function __invoke(TestCaseMethodFactory $method, array $attributes): array + { + foreach ($method->covers as $covering) { + if (is_array($covering)) { + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering[0]}]"; + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction({$covering[1]}]"; + } else { + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass($covering)]"; + } + } + + return $attributes; + } +} diff --git a/src/Factories/TestCaseMethodFactory.php b/src/Factories/TestCaseMethodFactory.php index 987a2d27..2c029162 100644 --- a/src/Factories/TestCaseMethodFactory.php +++ b/src/Factories/TestCaseMethodFactory.php @@ -47,6 +47,13 @@ final class TestCaseMethodFactory */ public array $groups = []; + /** + * The covered classes and methods, if any. + * + * @var array + */ + public array $covers = []; + /** * Creates a new Factory instance. */ @@ -108,7 +115,7 @@ final class TestCaseMethodFactory * * @param array $annotationsToUse */ - public function buildForEvaluation(string $classFQN, array $annotationsToUse): string + public function buildForEvaluation(string $classFQN, array $annotationsToUse, array $attributesToUse): string { if ($this->description === null) { throw ShouldNotHappen::fromMessage('The test description may not be empty.'); @@ -122,12 +129,18 @@ final class TestCaseMethodFactory $datasetsCode = ''; $annotations = ['@test']; + $attributes = []; foreach ($annotationsToUse as $annotation) { /** @phpstan-ignore-next-line */ $annotations = (new $annotation())->__invoke($this, $annotations); } + foreach ($attributesToUse as $attribute) { + /** @phpstan-ignore-next-line */ + $attributes = (new $attribute())->__invoke($this, $attributes); + } + if (count($this->datasets) > 0) { $dataProviderName = $methodName . '_dataset'; $annotations[] = "@dataProvider $dataProviderName"; @@ -138,10 +151,15 @@ final class TestCaseMethodFactory static fn ($annotation) => sprintf("\n * %s", $annotation), $annotations, )); + $attributes = implode('', array_map( + static fn ($attribute) => sprintf("\n %s", $attribute), $attributes, + )); + return <<__runTest( diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index f9e786c1..53a0cd2f 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Pest\PendingCalls; use Closure; +use InvalidArgumentException; use Pest\Factories\TestCaseMethodFactory; use Pest\Support\Backtrace; use Pest\Support\HigherOrderCallables; @@ -168,6 +169,25 @@ final class TestCall return $this; } + /** + * Sets the covered class and method. + */ + public function covers(string|array ...$classes): TestCall + { + foreach ($classes as $i => $class) { + if (is_array($class) && count($class) !== 2) { + throw new InvalidArgumentException(sprintf( + 'The #%s covered class must be an array with exactly 2 items: class and method name.', + $i + )); + } + + $this->testCaseMethod->covers[] = $class; + } + + return $this; + } + /** * Saves the property accessors to be used on the target. */ From 2465b884622197688e6b2e97c9190c44f19a5951 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Sat, 5 Mar 2022 16:23:05 +0100 Subject: [PATCH 09/32] add covers list and attributes mutator --- src/Factories/Attributes/Covers.php | 15 +++++++--- src/Factories/Covers/CoversClass.php | 16 ++++++++++ src/Factories/Covers/CoversFunction.php | 16 ++++++++++ src/Factories/Covers/CoversNothing.php | 13 ++++++++ src/Factories/TestCaseFactory.php | 11 ++++++- src/Factories/TestCaseMethodFactory.php | 2 +- src/PendingCalls/TestCall.php | 40 ++++++++++++++++++------- 7 files changed, 96 insertions(+), 17 deletions(-) create mode 100644 src/Factories/Covers/CoversClass.php create mode 100644 src/Factories/Covers/CoversFunction.php create mode 100644 src/Factories/Covers/CoversNothing.php diff --git a/src/Factories/Attributes/Covers.php b/src/Factories/Attributes/Covers.php index 2c6234f3..946bd1fd 100644 --- a/src/Factories/Attributes/Covers.php +++ b/src/Factories/Attributes/Covers.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace Pest\Factories\Attributes; +use Pest\Factories\Covers\CoversClass; +use Pest\Factories\Covers\CoversFunction; use Pest\Factories\TestCaseMethodFactory; /** @@ -22,11 +24,16 @@ final class Covers public function __invoke(TestCaseMethodFactory $method, array $attributes): array { foreach ($method->covers as $covering) { - if (is_array($covering)) { - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering[0]}]"; - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction({$covering[1]}]"; + if ($covering instanceof CoversClass) { + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering->class}]"; + + if (!is_null($covering->method)) { + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction({$covering->method}]"; + } + } else if ($covering instanceof CoversFunction) { + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction({$covering->function}]"; } else { - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass($covering)]"; + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversNothing]"; } } diff --git a/src/Factories/Covers/CoversClass.php b/src/Factories/Covers/CoversClass.php new file mode 100644 index 00000000..934660fd --- /dev/null +++ b/src/Factories/Covers/CoversClass.php @@ -0,0 +1,16 @@ + + */ + private static array $attributes = [ + Attributes\Covers::class, + ]; + /** * The FQN of the Test Case class. * @@ -142,7 +151,7 @@ final class TestCaseFactory } $methodsCode = implode('', array_map( - fn (TestCaseMethodFactory $methodFactory) => $methodFactory->buildForEvaluation($classFQN, self::$annotations), + fn (TestCaseMethodFactory $methodFactory) => $methodFactory->buildForEvaluation($classFQN, self::$annotations, self::$attributes), $methods )); diff --git a/src/Factories/TestCaseMethodFactory.php b/src/Factories/TestCaseMethodFactory.php index 2c029162..aac6c8dc 100644 --- a/src/Factories/TestCaseMethodFactory.php +++ b/src/Factories/TestCaseMethodFactory.php @@ -50,7 +50,7 @@ final class TestCaseMethodFactory /** * The covered classes and methods, if any. * - * @var array + * @var array */ public array $covers = []; diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index 53a0cd2f..a7c1621e 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -5,7 +5,9 @@ declare(strict_types=1); namespace Pest\PendingCalls; use Closure; -use InvalidArgumentException; +use Pest\Factories\Covers\CoversClass; +use Pest\Factories\Covers\CoversFunction; +use Pest\Factories\Covers\CoversNothing; use Pest\Factories\TestCaseMethodFactory; use Pest\Support\Backtrace; use Pest\Support\HigherOrderCallables; @@ -171,19 +173,35 @@ final class TestCall /** * Sets the covered class and method. + * + * @param class-string $class + * @param string|null $method */ - public function covers(string|array ...$classes): TestCall + public function covers(string $class, ?string $method = null): TestCall { - foreach ($classes as $i => $class) { - if (is_array($class) && count($class) !== 2) { - throw new InvalidArgumentException(sprintf( - 'The #%s covered class must be an array with exactly 2 items: class and method name.', - $i - )); - } + $this->testCaseMethod->covers[] = new CoversClass(...func_get_args()); - $this->testCaseMethod->covers[] = $class; - } + return $this; + } + + /** + * Sets the covered function. + * + * @param string $method + */ + public function coversFunction(string $method): TestCall + { + $this->testCaseMethod->covers[] = new CoversFunction(...func_get_args()); + + return $this; + } + + /** + * Sets that the current test covers nothing. + */ + public function coversNothing(): TestCall + { + $this->testCaseMethod->covers[] = new CoversNothing(); return $this; } From a894386b49d1b02e12b54d5788db16ecd0987e6d Mon Sep 17 00:00:00 2001 From: danilopolani Date: Sat, 5 Mar 2022 16:51:12 +0100 Subject: [PATCH 10/32] pass methods name to attribute surrounded by quotes --- src/Factories/Attributes/Covers.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Factories/Attributes/Covers.php b/src/Factories/Attributes/Covers.php index 946bd1fd..a965ca21 100644 --- a/src/Factories/Attributes/Covers.php +++ b/src/Factories/Attributes/Covers.php @@ -28,10 +28,10 @@ final class Covers $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering->class}]"; if (!is_null($covering->method)) { - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction({$covering->method}]"; + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->method}']"; } } else if ($covering instanceof CoversFunction) { - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction({$covering->function}]"; + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->function}']"; } else { $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversNothing]"; } From 27baad82d03fbe397d7a7a94d132e7506ba52fa2 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Sat, 5 Mar 2022 17:03:45 +0100 Subject: [PATCH 11/32] remove method name on coversClass --- src/Factories/Attributes/Covers.php | 4 ---- src/Factories/Covers/CoversClass.php | 2 +- src/PendingCalls/TestCall.php | 3 +-- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Factories/Attributes/Covers.php b/src/Factories/Attributes/Covers.php index a965ca21..136dd432 100644 --- a/src/Factories/Attributes/Covers.php +++ b/src/Factories/Attributes/Covers.php @@ -26,10 +26,6 @@ final class Covers foreach ($method->covers as $covering) { if ($covering instanceof CoversClass) { $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering->class}]"; - - if (!is_null($covering->method)) { - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->method}']"; - } } else if ($covering instanceof CoversFunction) { $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->function}']"; } else { diff --git a/src/Factories/Covers/CoversClass.php b/src/Factories/Covers/CoversClass.php index 934660fd..dbc3fb86 100644 --- a/src/Factories/Covers/CoversClass.php +++ b/src/Factories/Covers/CoversClass.php @@ -9,7 +9,7 @@ namespace Pest\Factories\Covers; */ final class CoversClass { - public function __construct(public string $class, public ?string $method = null) + public function __construct(public string $class) { // } diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index a7c1621e..3ac00ff1 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -175,9 +175,8 @@ final class TestCall * Sets the covered class and method. * * @param class-string $class - * @param string|null $method */ - public function covers(string $class, ?string $method = null): TestCall + public function covers(string $class): TestCall { $this->testCaseMethod->covers[] = new CoversClass(...func_get_args()); From 50d8688b79f02994581013f6ac8062a4c426087b Mon Sep 17 00:00:00 2001 From: danilopolani Date: Sat, 5 Mar 2022 17:06:00 +0100 Subject: [PATCH 12/32] allow multiple values on coversClass and coversFunction --- src/PendingCalls/TestCall.php | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index 3ac00ff1..b745ff4c 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -172,25 +172,29 @@ final class TestCall } /** - * Sets the covered class and method. + * Sets the covered classes. * - * @param class-string $class + * @param class-string..., $classes */ - public function covers(string $class): TestCall + public function coversClass(string ...$classes): TestCall { - $this->testCaseMethod->covers[] = new CoversClass(...func_get_args()); + foreach ($classes as $class) { + $this->testCaseMethod->covers[] = new CoversClass($class); + } return $this; } /** - * Sets the covered function. + * Sets the covered functions. * - * @param string $method + * @param string..., $functions */ - public function coversFunction(string $method): TestCall + public function coversFunction(string ...$functions): TestCall { - $this->testCaseMethod->covers[] = new CoversFunction(...func_get_args()); + foreach ($functions as $function) { + $this->testCaseMethod->covers[] = new CoversFunction($function); + } return $this; } From 21364779f994f3e96ff81bdfd207430bd4e73c26 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Sat, 5 Mar 2022 17:23:03 +0100 Subject: [PATCH 13/32] move covers attribute above the class --- src/Factories/Attributes/Attribute.php | 18 ++++++++++++++++++ src/Factories/Attributes/Covers.php | 9 ++++++++- src/Factories/TestCaseFactory.php | 16 +++++++++++++++- src/Factories/TestCaseMethodFactory.php | 11 ----------- 4 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 src/Factories/Attributes/Attribute.php diff --git a/src/Factories/Attributes/Attribute.php b/src/Factories/Attributes/Attribute.php new file mode 100644 index 00000000..2eaf8dbf --- /dev/null +++ b/src/Factories/Attributes/Attribute.php @@ -0,0 +1,18 @@ + + * @var array */ private static array $attributes = [ Attributes\Covers::class, @@ -155,6 +155,19 @@ final class TestCaseFactory $methods )); + $classAttributes = []; + + foreach (self::$attributes as $attribute) { + if ($attribute::ABOVE_CLASS) { + /** @phpstan-ignore-next-line */ + $classAttributes = (new $attribute())->__invoke($this, $classAttributes); + } + } + + $classAttributes = implode('', array_map( + static fn ($attribute) => sprintf("\n %s", $attribute), $classAttributes, + )); + try { eval(" namespace $namespace; @@ -162,6 +175,7 @@ final class TestCaseFactory use Pest\Repositories\DatasetsRepository as __PestDatasets; use Pest\TestSuite as __PestTestSuite; + $classAttributes final class $className extends $baseClass implements $hasPrintableTestCaseClassFQN { $traitsCode diff --git a/src/Factories/TestCaseMethodFactory.php b/src/Factories/TestCaseMethodFactory.php index aac6c8dc..bb9e6721 100644 --- a/src/Factories/TestCaseMethodFactory.php +++ b/src/Factories/TestCaseMethodFactory.php @@ -129,18 +129,12 @@ final class TestCaseMethodFactory $datasetsCode = ''; $annotations = ['@test']; - $attributes = []; foreach ($annotationsToUse as $annotation) { /** @phpstan-ignore-next-line */ $annotations = (new $annotation())->__invoke($this, $annotations); } - foreach ($attributesToUse as $attribute) { - /** @phpstan-ignore-next-line */ - $attributes = (new $attribute())->__invoke($this, $attributes); - } - if (count($this->datasets) > 0) { $dataProviderName = $methodName . '_dataset'; $annotations[] = "@dataProvider $dataProviderName"; @@ -151,15 +145,10 @@ final class TestCaseMethodFactory static fn ($annotation) => sprintf("\n * %s", $annotation), $annotations, )); - $attributes = implode('', array_map( - static fn ($attribute) => sprintf("\n %s", $attribute), $attributes, - )); - return <<__runTest( From 1079793ccf3a6a8218f13c9afeac26c410cd9b86 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Sat, 5 Mar 2022 17:25:23 +0100 Subject: [PATCH 14/32] cleanup --- src/Factories/TestCaseFactory.php | 2 +- src/Factories/TestCaseMethodFactory.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index f9152b49..5f51389c 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -151,7 +151,7 @@ final class TestCaseFactory } $methodsCode = implode('', array_map( - fn (TestCaseMethodFactory $methodFactory) => $methodFactory->buildForEvaluation($classFQN, self::$annotations, self::$attributes), + fn (TestCaseMethodFactory $methodFactory) => $methodFactory->buildForEvaluation($classFQN, self::$annotations), $methods )); diff --git a/src/Factories/TestCaseMethodFactory.php b/src/Factories/TestCaseMethodFactory.php index bb9e6721..21118b8f 100644 --- a/src/Factories/TestCaseMethodFactory.php +++ b/src/Factories/TestCaseMethodFactory.php @@ -48,7 +48,7 @@ final class TestCaseMethodFactory public array $groups = []; /** - * The covered classes and methods, if any. + * The covered classes and functions, if any. * * @var array */ @@ -115,7 +115,7 @@ final class TestCaseMethodFactory * * @param array $annotationsToUse */ - public function buildForEvaluation(string $classFQN, array $annotationsToUse, array $attributesToUse): string + public function buildForEvaluation(string $classFQN, array $annotationsToUse): string { if ($this->description === null) { throw ShouldNotHappen::fromMessage('The test description may not be empty.'); From 1dc33070fe6b7db23189507cacdb3ebe262186b0 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Sun, 6 Mar 2022 19:02:02 +0100 Subject: [PATCH 15/32] fix phpdoc --- src/Factories/TestCaseFactory.php | 2 +- src/PendingCalls/TestCall.php | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index 5f51389c..76014818 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -38,7 +38,7 @@ final class TestCaseFactory /** * The list of annotations. * - * @var array + * @var array */ private static array $attributes = [ Attributes\Covers::class, diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index b745ff4c..7dca121b 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -173,8 +173,6 @@ final class TestCall /** * Sets the covered classes. - * - * @param class-string..., $classes */ public function coversClass(string ...$classes): TestCall { @@ -187,8 +185,6 @@ final class TestCall /** * Sets the covered functions. - * - * @param string..., $functions */ public function coversFunction(string ...$functions): TestCall { From 32dbac87c8927c22a7116de31182c334f0409913 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Mon, 7 Mar 2022 16:18:55 +0100 Subject: [PATCH 16/32] fix fqn on coversClass attribute and array evaluation --- src/Factories/Attributes/Covers.php | 4 ++-- src/Factories/TestCaseFactory.php | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Factories/Attributes/Covers.php b/src/Factories/Attributes/Covers.php index e474e67e..67cf44ad 100644 --- a/src/Factories/Attributes/Covers.php +++ b/src/Factories/Attributes/Covers.php @@ -32,9 +32,9 @@ final class Covers extends Attribute { foreach ($method->covers as $covering) { if ($covering instanceof CoversClass) { - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering->class}]"; + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering->class}::class)]"; } else if ($covering instanceof CoversFunction) { - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->function}']"; + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->function}')]"; } else { $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversNothing]"; } diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index 76014818..d568ee3e 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -159,13 +159,15 @@ final class TestCaseFactory foreach (self::$attributes as $attribute) { if ($attribute::ABOVE_CLASS) { - /** @phpstan-ignore-next-line */ - $classAttributes = (new $attribute())->__invoke($this, $classAttributes); + foreach ($methods as $methodFactory) { + $classAttributes = (new $attribute())->__invoke($methodFactory, $classAttributes); + } } } $classAttributes = implode('', array_map( - static fn ($attribute) => sprintf("\n %s", $attribute), $classAttributes, + static fn ($attribute) => sprintf("\n %s", $attribute), + array_unique($classAttributes), )); try { From 443f8483864c59526d4655805754004e8469258b Mon Sep 17 00:00:00 2001 From: danilopolani Date: Mon, 7 Mar 2022 17:40:29 +0100 Subject: [PATCH 17/32] fix fqn for coversClass --- src/Factories/Attributes/Covers.php | 5 +++++ src/Factories/TestCaseFactory.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Factories/Attributes/Covers.php b/src/Factories/Attributes/Covers.php index 67cf44ad..1d0e6991 100644 --- a/src/Factories/Attributes/Covers.php +++ b/src/Factories/Attributes/Covers.php @@ -32,6 +32,11 @@ final class Covers extends Attribute { foreach ($method->covers as $covering) { if ($covering instanceof CoversClass) { + // Prepend a backslash for FQN classes + if (str_contains($covering->class, '\\')) { + $covering->class = '\\' . $covering->class; + } + $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering->class}::class)]"; } else if ($covering instanceof CoversFunction) { $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->function}')]"; diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index d568ee3e..2fb6d429 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -166,7 +166,7 @@ final class TestCaseFactory } $classAttributes = implode('', array_map( - static fn ($attribute) => sprintf("\n %s", $attribute), + static fn (string $attribute) => sprintf("\n %s", $attribute), array_unique($classAttributes), )); From 985bbf4ea57bbf4b3b9344625b95ff183482245a Mon Sep 17 00:00:00 2001 From: danilopolani Date: Mon, 7 Mar 2022 17:40:43 +0100 Subject: [PATCH 18/32] add tests for covers attribute --- tests/Features/Covers.php | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/Features/Covers.php diff --git a/tests/Features/Covers.php b/tests/Features/Covers.php new file mode 100644 index 00000000..704168c3 --- /dev/null +++ b/tests/Features/Covers.php @@ -0,0 +1,46 @@ +getAttributes(); + + expect($attributes[0]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); + expect($attributes[0]->getArguments()[0])->toBe('P\Tests\Features\TestCoversClass1'); +})->coversClass(TestCoversClass1::class); + +it('uses the correct PHPUnit attribute for function', function () { + $attributes = (new ReflectionClass($this))->getAttributes(); + + expect($attributes[1]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); + expect($attributes[1]->getArguments()[0])->toBe('foo'); +})->coversFunction('foo'); + +it('uses the correct PHPUnit attribute for nothing', function () { + $attributes = (new ReflectionClass($this))->getAttributes(); + + expect($attributes[2]->getName())->toBe('PHPUnit\Framework\Attributes\CoversNothing'); +})->coversNothing(); + +it('removes duplicated attributes', function () { + $attributes = (new ReflectionClass($this))->getAttributes(); + + expect($attributes)->toHaveCount(7); // 3 classes, 3 functions, 1 nothing + + expect($attributes[3]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); + expect($attributes[3]->getArguments()[0])->toBe('P\Tests\Features\TestCoversClass2'); + expect($attributes[4]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); + expect($attributes[4]->getArguments()[0])->toBe('Pest\Factories\Attributes\Covers'); + expect($attributes[5]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); + expect($attributes[5]->getArguments()[0])->toBe('bar'); + expect($attributes[6]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); + expect($attributes[6]->getArguments()[0])->toBe('baz'); +}) + ->coversClass(TestCoversClass2::class, TestCoversClass1::class, Covers::class) + ->coversNothing() + ->coversFunction('bar', 'foo', 'baz'); From edd1d890ca10d6d553a85835e49e63bb1f3be51f Mon Sep 17 00:00:00 2001 From: danilopolani Date: Mon, 7 Mar 2022 17:51:39 +0100 Subject: [PATCH 19/32] replace double foreach with a filter and reduce --- src/Factories/TestCaseFactory.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index 2fb6d429..81d11aa6 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -155,19 +155,20 @@ final class TestCaseFactory $methods )); - $classAttributes = []; + $classAttributesCode = []; + $classAvailableAttributes = array_filter(self::$attributes, fn (string $attribute) => $attribute::ABOVE_CLASS); - foreach (self::$attributes as $attribute) { - if ($attribute::ABOVE_CLASS) { - foreach ($methods as $methodFactory) { - $classAttributes = (new $attribute())->__invoke($methodFactory, $classAttributes); - } - } + foreach ($classAvailableAttributes as $attribute) { + $classAttributesCode = array_reduce( + $methods, + fn (array $carry, TestCaseMethodFactory $methodFactory) => (new $attribute())->__invoke($methodFactory, $carry), + $classAttributesCode + ); } - $classAttributes = implode('', array_map( + $classAttributesCode = implode('', array_map( static fn (string $attribute) => sprintf("\n %s", $attribute), - array_unique($classAttributes), + array_unique($classAttributesCode), )); try { @@ -177,7 +178,7 @@ final class TestCaseFactory use Pest\Repositories\DatasetsRepository as __PestDatasets; use Pest\TestSuite as __PestTestSuite; - $classAttributes + $classAttributesCode final class $className extends $baseClass implements $hasPrintableTestCaseClassFQN { $traitsCode From a5cbdea868f7e311aef06bf9465613b2000da96d Mon Sep 17 00:00:00 2001 From: danilopolani Date: Mon, 7 Mar 2022 17:51:47 +0100 Subject: [PATCH 20/32] fix phpstan issues --- src/Factories/Attributes/Covers.php | 3 +-- src/Factories/Covers/CoversClass.php | 1 - src/Factories/Covers/CoversFunction.php | 1 - src/Factories/Covers/CoversNothing.php | 1 - tests/Features/Covers.php | 10 ++++++++-- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Factories/Attributes/Covers.php b/src/Factories/Attributes/Covers.php index 1d0e6991..1c41608b 100644 --- a/src/Factories/Attributes/Covers.php +++ b/src/Factories/Attributes/Covers.php @@ -23,7 +23,6 @@ final class Covers extends Attribute /** * Adds attributes regarding the "covers" feature. * - * @param \Pest\Factories\TestCaseMethodFactory $method * @param array $attributes * * @return array @@ -38,7 +37,7 @@ final class Covers extends Attribute } $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering->class}::class)]"; - } else if ($covering instanceof CoversFunction) { + } elseif ($covering instanceof CoversFunction) { $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->function}')]"; } else { $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversNothing]"; diff --git a/src/Factories/Covers/CoversClass.php b/src/Factories/Covers/CoversClass.php index dbc3fb86..44f58487 100644 --- a/src/Factories/Covers/CoversClass.php +++ b/src/Factories/Covers/CoversClass.php @@ -11,6 +11,5 @@ final class CoversClass { public function __construct(public string $class) { - // } } diff --git a/src/Factories/Covers/CoversFunction.php b/src/Factories/Covers/CoversFunction.php index 5fddce9c..5759bbc7 100644 --- a/src/Factories/Covers/CoversFunction.php +++ b/src/Factories/Covers/CoversFunction.php @@ -11,6 +11,5 @@ final class CoversFunction { public function __construct(public string $function) { - // } } diff --git a/src/Factories/Covers/CoversNothing.php b/src/Factories/Covers/CoversNothing.php index 183f5b74..31b3d310 100644 --- a/src/Factories/Covers/CoversNothing.php +++ b/src/Factories/Covers/CoversNothing.php @@ -9,5 +9,4 @@ namespace Pest\Factories\Covers; */ final class CoversNothing { - // } diff --git a/tests/Features/Covers.php b/tests/Features/Covers.php index 704168c3..f52d0740 100644 --- a/tests/Features/Covers.php +++ b/tests/Features/Covers.php @@ -4,8 +4,14 @@ use Pest\Factories\Attributes\Covers; $runCounter = 0; -class TestCoversClass1 {} -class TestCoversClass2 {} +class TestCoversClass1 +{ + +} +class TestCoversClass2 +{ + +} it('uses the correct PHPUnit attribute for class', function () { $attributes = (new ReflectionClass($this))->getAttributes(); From 00029c15ef64dcdcf95fdcd1aa9fc6eb6dd1b603 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Mon, 7 Mar 2022 18:22:30 +0100 Subject: [PATCH 21/32] add generic covers method to accept both classes and functions --- src/PendingCalls/TestCall.php | 26 ++++++++++++++++++++++++++ tests/Features/Covers.php | 27 +++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index 7dca121b..82dd4b65 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Pest\PendingCalls; use Closure; +use InvalidArgumentException; use Pest\Factories\Covers\CoversClass; use Pest\Factories\Covers\CoversFunction; use Pest\Factories\Covers\CoversNothing; @@ -171,6 +172,31 @@ final class TestCall return $this; } + /** + * Sets the covered classes or methods. + */ + public function covers(string ...$classesOrFunctions): TestCall + { + foreach ($classesOrFunctions as $classOrFunction) { + $isClass = class_exists($classOrFunction); + $isMethod = function_exists($classOrFunction); + + if (!$isClass && !$isMethod) { + throw new InvalidArgumentException( + sprintf('No class or method named "%s" has been found.', $classOrFunction) + ); + } + + if ($isClass) { + $this->coversClass($classOrFunction); + } else { + $this->coversFunction($classOrFunction); + } + } + + return $this; + } + /** * Sets the covered classes. */ diff --git a/tests/Features/Covers.php b/tests/Features/Covers.php index f52d0740..b41b3f8a 100644 --- a/tests/Features/Covers.php +++ b/tests/Features/Covers.php @@ -1,18 +1,24 @@ getAttributes(); @@ -36,8 +42,6 @@ it('uses the correct PHPUnit attribute for nothing', function () { it('removes duplicated attributes', function () { $attributes = (new ReflectionClass($this))->getAttributes(); - expect($attributes)->toHaveCount(7); // 3 classes, 3 functions, 1 nothing - expect($attributes[3]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); expect($attributes[3]->getArguments()[0])->toBe('P\Tests\Features\TestCoversClass2'); expect($attributes[4]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); @@ -50,3 +54,18 @@ it('removes duplicated attributes', function () { ->coversClass(TestCoversClass2::class, TestCoversClass1::class, Covers::class) ->coversNothing() ->coversFunction('bar', 'foo', 'baz'); + +it('guesses if the given argument is a class or function', function () { + $attributes = (new ReflectionClass($this))->getAttributes(); + + expect($attributes[7]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); + expect($attributes[7]->getArguments()[0])->toBe('P\Tests\Features\TestCoversClass3'); + expect($attributes[8]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); + expect($attributes[8]->getArguments()[0])->toBe('testCoversFunction'); +})->covers(TestCoversClass3::class, 'testCoversFunction'); + +it('throws exception if no class nor method has been found', function () { + $testCall = new TestCall(TestSuite::getInstance(), 'filename', 'description', fn () => 'closure'); + + $testCall->covers('fakeName'); +})->throws(InvalidArgumentException::class, 'No class or method named "fakeName" has been found.'); From d0136b63d47b03126e5cbc39a384494f98ad03a7 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Mon, 7 Mar 2022 18:23:06 +0100 Subject: [PATCH 22/32] fix linting --- src/PendingCalls/TestCall.php | 6 ++---- tests/Features/Covers.php | 4 +++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index 82dd4b65..bc125599 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -178,13 +178,11 @@ final class TestCall public function covers(string ...$classesOrFunctions): TestCall { foreach ($classesOrFunctions as $classOrFunction) { - $isClass = class_exists($classOrFunction); + $isClass = class_exists($classOrFunction); $isMethod = function_exists($classOrFunction); if (!$isClass && !$isMethod) { - throw new InvalidArgumentException( - sprintf('No class or method named "%s" has been found.', $classOrFunction) - ); + throw new InvalidArgumentException(sprintf('No class or method named "%s" has been found.', $classOrFunction)); } if ($isClass) { diff --git a/tests/Features/Covers.php b/tests/Features/Covers.php index b41b3f8a..3b9d6809 100644 --- a/tests/Features/Covers.php +++ b/tests/Features/Covers.php @@ -17,7 +17,9 @@ class TestCoversClass3 { } -function testCoversFunction() { } +function testCoversFunction() +{ +} it('uses the correct PHPUnit attribute for class', function () { $attributes = (new ReflectionClass($this))->getAttributes(); From 3601d01bd5dc8e68c60d5cfaea44e804b7a29531 Mon Sep 17 00:00:00 2001 From: Markus Hebenstreit Date: Tue, 8 Mar 2022 10:41:09 +0100 Subject: [PATCH 23/32] Added dump helper to Expectation class --- src/Expectation.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Expectation.php b/src/Expectation.php index 7703ebb8..1099daff 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -76,6 +76,22 @@ final class Expectation return $this->toBeJson()->and($value); } + /** + * Dump the expectation value. + * + * @return self + */ + public function dump(mixed ...$arguments): self + { + if (function_exists('dump')) { + dump($this->value, ...$arguments); + } else { + var_dump($this->value); + } + + return $this; + } + /** * Dump the expectation value and end the script. * From 3ffed844a62ab43ee47eca99fa307fa9b81d706c Mon Sep 17 00:00:00 2001 From: Owen Voke Date: Tue, 8 Mar 2022 10:51:38 +0000 Subject: [PATCH 24/32] style: apply fixes from PHP-CS-Fixer --- src/Concerns/Pipeable.php | 2 +- src/Expectation.php | 2 +- src/Kernel.php | 2 +- src/Mixins/Expectation.php | 6 +++--- src/Repositories/DatasetsRepository.php | 6 +++--- src/Support/Container.php | 2 +- src/Support/HigherOrderMessageCollection.php | 2 +- tests/Features/Coverage.php | 2 +- tests/Features/Expect/pipes.php | 10 +++++----- tests/Features/Expect/toBe.php | 2 +- tests/Features/Expect/toHaveProperties.php | 10 +++++----- tests/Features/Expect/unless.php | 4 ++-- tests/Features/Expect/when.php | 4 ++-- tests/Unit/Support/Reflection.php | 2 +- tests/Unit/TestSuite.php | 6 +++--- tests/Visual/Help.php | 2 +- tests/Visual/Success.php | 2 +- 17 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/Concerns/Pipeable.php b/src/Concerns/Pipeable.php index 79f32055..d1df162e 100644 --- a/src/Concerns/Pipeable.php +++ b/src/Concerns/Pipeable.php @@ -43,7 +43,7 @@ trait Pipeable $this->pipe($name, function ($next, ...$arguments) use ($handler, $filter) { /* @phpstan-ignore-next-line */ if ($filter($this->value, ...$arguments)) { - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line $handler->bindTo($this, get_class($this))(...$arguments); return; diff --git a/src/Expectation.php b/src/Expectation.php index 1099daff..fd771e41 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -307,7 +307,7 @@ final class Expectation private function getExpectationClosure(string $name): Closure { if (method_exists(Mixins\Expectation::class, $name)) { - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line return Closure::fromCallable([new Mixins\Expectation($this->value), $name]); } diff --git a/src/Kernel.php b/src/Kernel.php index 67c4dcf9..98bf867c 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -37,7 +37,7 @@ final class Kernel public static function boot(): self { foreach (self::$bootstrappers as $bootstrapper) { - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line (new $bootstrapper())->__invoke(); } diff --git a/src/Mixins/Expectation.php b/src/Mixins/Expectation.php index 5823d61c..337cc9cc 100644 --- a/src/Mixins/Expectation.php +++ b/src/Mixins/Expectation.php @@ -283,7 +283,7 @@ final class Expectation { $this->toBeObject(); - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line Assert::assertTrue(property_exists($this->value, $name)); if (func_num_args() > 1) { @@ -534,7 +534,7 @@ final class Expectation { Assert::assertIsString($this->value); - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line Assert::assertJson($this->value); return $this; @@ -580,7 +580,7 @@ final class Expectation try { Assert::assertTrue(Arr::has($array, $key)); - /* @phpstan-ignore-next-line */ + /* @phpstan-ignore-next-line */ } catch (ExpectationFailedException $exception) { throw new ExpectationFailedException("Failed asserting that an array has the key '$key'", $exception->getComparisonFailure()); } diff --git a/src/Repositories/DatasetsRepository.php b/src/Repositories/DatasetsRepository.php index d8a57bfa..385d4d47 100644 --- a/src/Repositories/DatasetsRepository.php +++ b/src/Repositories/DatasetsRepository.php @@ -156,11 +156,11 @@ final class DatasetsRepository $datasets[$index] = iterator_to_array($datasets[$index]); } - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line foreach ($datasets[$index] as $key => $values) { $values = is_array($values) ? $values : [$values]; $processedDataset[] = [ - 'label' => self::getDatasetDescription($key, $values), //@phpstan-ignore-line + 'label' => self::getDatasetDescription($key, $values), // @phpstan-ignore-line 'values' => $values, ]; } @@ -189,7 +189,7 @@ final class DatasetsRepository $result = $tmp; } - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line return $result; } diff --git a/src/Support/Container.php b/src/Support/Container.php index 1f6b45cd..67cd4e39 100644 --- a/src/Support/Container.php +++ b/src/Support/Container.php @@ -85,7 +85,7 @@ final class Container } } - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line return $this->get($candidate); }, $constructor->getParameters() diff --git a/src/Support/HigherOrderMessageCollection.php b/src/Support/HigherOrderMessageCollection.php index 54bef82a..6d4bca2b 100644 --- a/src/Support/HigherOrderMessageCollection.php +++ b/src/Support/HigherOrderMessageCollection.php @@ -40,7 +40,7 @@ final class HigherOrderMessageCollection public function chain(object $target): void { foreach ($this->messages as $message) { - //@phpstan-ignore-next-line + // @phpstan-ignore-next-line $target = $message->call($target) ?? $target; } } diff --git a/tests/Features/Coverage.php b/tests/Features/Coverage.php index e43ae180..7af61548 100644 --- a/tests/Features/Coverage.php +++ b/tests/Features/Coverage.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Output\ConsoleOutput; it('has plugin')->assertTrue(class_exists(CoveragePlugin::class)); it('adds coverage if --coverage exist', function () { - $plugin = new CoveragePlugin(new ConsoleOutput()); + $plugin = new CoveragePlugin(new ConsoleOutput()); $testSuite = TestSuite::getInstance(); expect($plugin->coverage)->toBeFalse(); diff --git a/tests/Features/Expect/pipes.php b/tests/Features/Expect/pipes.php index 5e311e07..25723f68 100644 --- a/tests/Features/Expect/pipes.php +++ b/tests/Features/Expect/pipes.php @@ -12,7 +12,7 @@ class Number public function __construct( public int $value ) { - //.. + // .. } } @@ -21,7 +21,7 @@ class Char public function __construct( public string $value ) { - //.. + // .. } } @@ -30,7 +30,7 @@ class Symbol public function __construct( public string $value ) { - //.. + // .. } } @@ -69,11 +69,11 @@ expect()->pipe('toBe', function ($next, $expected) use ($state) { assertInstanceOf(Char::class, $expected); assertEquals($this->value->value, $expected->value); - //returning nothing stops pipeline execution + // returning nothing stops pipeline execution return; } - //calling $next(); let the pipeline to keep running + // calling $next(); let the pipeline to keep running $next(); }); diff --git a/tests/Features/Expect/toBe.php b/tests/Features/Expect/toBe.php index ef2bce5a..d73760b3 100644 --- a/tests/Features/Expect/toBe.php +++ b/tests/Features/Expect/toBe.php @@ -5,7 +5,7 @@ use PHPUnit\Framework\ExpectationFailedException; expect(true)->toBeTrue()->and(false)->toBeFalse(); test('strict comparisons', function () { - $nuno = new stdClass(); + $nuno = new stdClass(); $dries = new stdClass(); expect($nuno)->toBe($nuno)->not->toBe($dries); diff --git a/tests/Features/Expect/toHaveProperties.php b/tests/Features/Expect/toHaveProperties.php index ad3da1b0..aae1303c 100644 --- a/tests/Features/Expect/toHaveProperties.php +++ b/tests/Features/Expect/toHaveProperties.php @@ -3,24 +3,24 @@ use PHPUnit\Framework\ExpectationFailedException; test('pass', function () { - $object = new stdClass(); + $object = new stdClass(); $object->name = 'Jhon'; - $object->age = 21; + $object->age = 21; expect($object)->toHaveProperties(['name', 'age']); }); test('failures', function () { - $object = new stdClass(); + $object = new stdClass(); $object->name = 'Jhon'; expect($object)->toHaveProperties(['name', 'age']); })->throws(ExpectationFailedException::class); test('not failures', function () { - $object = new stdClass(); + $object = new stdClass(); $object->name = 'Jhon'; - $object->age = 21; + $object->age = 21; expect($object)->not->toHaveProperties(['name', 'age']); })->throws(ExpectationFailedException::class); diff --git a/tests/Features/Expect/unless.php b/tests/Features/Expect/unless.php index 9f11c7ef..0dabe2bb 100644 --- a/tests/Features/Expect/unless.php +++ b/tests/Features/Expect/unless.php @@ -3,9 +3,9 @@ use PHPUnit\Framework\ExpectationFailedException; beforeEach(function () { - $this->unlessObject = new stdClass(); + $this->unlessObject = new stdClass(); $this->unlessObject->trueValue = true; - $this->unlessObject->foo = 'foo'; + $this->unlessObject->foo = 'foo'; }); it('pass', function () { diff --git a/tests/Features/Expect/when.php b/tests/Features/Expect/when.php index db9fa4f1..3b62e2f8 100644 --- a/tests/Features/Expect/when.php +++ b/tests/Features/Expect/when.php @@ -3,9 +3,9 @@ use PHPUnit\Framework\ExpectationFailedException; beforeEach(function () { - $this->whenObject = new stdClass(); + $this->whenObject = new stdClass(); $this->whenObject->trueValue = true; - $this->whenObject->foo = 'foo'; + $this->whenObject->foo = 'foo'; }); it('pass', function () { diff --git a/tests/Unit/Support/Reflection.php b/tests/Unit/Support/Reflection.php index 7ad76b0d..7e98bd76 100644 --- a/tests/Unit/Support/Reflection.php +++ b/tests/Unit/Support/Reflection.php @@ -10,7 +10,7 @@ it('gets file name from closure', function () { }); it('gets property values', function () { - $class = new class() { + $class = new class() { private $foo = 'bar'; }; diff --git a/tests/Unit/TestSuite.php b/tests/Unit/TestSuite.php index a15ad631..807594be 100644 --- a/tests/Unit/TestSuite.php +++ b/tests/Unit/TestSuite.php @@ -8,7 +8,7 @@ use Pest\TestSuite; it('does not allow to add the same test description twice', function () { $testSuite = new TestSuite(getcwd(), 'tests'); - $method = new TestCaseMethodFactory('foo', 'bar', null); + $method = new TestCaseMethodFactory('foo', 'bar', null); $testSuite->tests->set($method); $testSuite->tests->set($method); @@ -43,7 +43,7 @@ it('can return an array of all test suite filenames', function () { it('can filter the test suite filenames to those with the only method', function () { $testSuite = new TestSuite(getcwd(), 'tests'); - $testWithOnly = new TestCaseMethodFactory('a', 'b', null); + $testWithOnly = new TestCaseMethodFactory('a', 'b', null); $testWithOnly->only = true; $testSuite->tests->set($testWithOnly); @@ -61,7 +61,7 @@ it('does not filter the test suite filenames to those with the only method when $test = function () {}; - $testWithOnly = new TestCaseMethodFactory('a', 'b', null); + $testWithOnly = new TestCaseMethodFactory('a', 'b', null); $testWithOnly->only = true; $testSuite->tests->set($testWithOnly); diff --git a/tests/Visual/Help.php b/tests/Visual/Help.php index e015108f..8088f9d3 100644 --- a/tests/Visual/Help.php +++ b/tests/Visual/Help.php @@ -8,7 +8,7 @@ test('visual snapshot of help command output', function () { if (getenv('REBUILD_SNAPSHOTS')) { $outputBuffer = new BufferedOutput(); - $plugin = new Help($outputBuffer); + $plugin = new Help($outputBuffer); $plugin(); diff --git a/tests/Visual/Success.php b/tests/Visual/Success.php index 4885255e..c64344f5 100644 --- a/tests/Visual/Success.php +++ b/tests/Visual/Success.php @@ -2,7 +2,7 @@ test('visual snapshot of test suite on success', function () { $testsPath = dirname(__DIR__); - $snapshot = implode(DIRECTORY_SEPARATOR, [ + $snapshot = implode(DIRECTORY_SEPARATOR, [ $testsPath, '.snapshots', 'success.txt', From 15e2e1711bf1ceeed0545cce5a5004d384163e20 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Tue, 8 Mar 2022 14:57:17 +0100 Subject: [PATCH 25/32] enforce class-string for attributes --- src/Factories/TestCaseFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index 81d11aa6..ed3d70e8 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -38,7 +38,7 @@ final class TestCaseFactory /** * The list of annotations. * - * @var array + * @var array> */ private static array $attributes = [ Attributes\Covers::class, From a027e24e3cd14050f2f18e0bef4ebd56fcdec764 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Tue, 8 Mar 2022 15:02:30 +0100 Subject: [PATCH 26/32] fix typo --- src/Factories/Attributes/Attribute.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Factories/Attributes/Attribute.php b/src/Factories/Attributes/Attribute.php index 2eaf8dbf..22a08968 100644 --- a/src/Factories/Attributes/Attribute.php +++ b/src/Factories/Attributes/Attribute.php @@ -10,7 +10,7 @@ namespace Pest\Factories\Attributes; abstract class Attribute { /** - * Determine if the attribute should be placed above the classe instead of above the method. + * Determine if the attribute should be placed above the class instead of above the method. * * @var bool */ From 24204adc09e558c2a3c1c62e4340052d11940340 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Wed, 9 Mar 2022 01:11:37 +0000 Subject: [PATCH 27/32] Adds `StandWithUkraine` banner --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3f710c49..8727bc84 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ + + +------ +

PEST

From 3795870150de8183c11fba1b9cfd4068bf4ea614 Mon Sep 17 00:00:00 2001 From: danilopolani Date: Wed, 9 Mar 2022 11:05:10 +0100 Subject: [PATCH 28/32] move coversNothing to method annotations --- src/Factories/Annotations/CoversNothing.php | 30 ++++++++++++++++ src/Factories/Attributes/Covers.php | 2 -- src/Factories/TestCaseFactory.php | 27 ++++++++------ src/Factories/TestCaseMethodFactory.php | 14 +++++++- src/PendingCalls/TestCall.php | 2 +- tests/Features/Covers.php | 39 ++++++++++++--------- 6 files changed, 83 insertions(+), 31 deletions(-) create mode 100644 src/Factories/Annotations/CoversNothing.php diff --git a/src/Factories/Annotations/CoversNothing.php b/src/Factories/Annotations/CoversNothing.php new file mode 100644 index 00000000..8faaca1f --- /dev/null +++ b/src/Factories/Annotations/CoversNothing.php @@ -0,0 +1,30 @@ + $annotations + * + * @return array + */ + public function __invoke(TestCaseMethodFactory $method, array $annotations): array + { + if (($method->covers[0] ?? null) instanceof CoversNothingFactory) { + $annotations[] = '@coversNothing'; + } + + return $annotations; + } +} diff --git a/src/Factories/Attributes/Covers.php b/src/Factories/Attributes/Covers.php index 1c41608b..d6d41c4a 100644 --- a/src/Factories/Attributes/Covers.php +++ b/src/Factories/Attributes/Covers.php @@ -39,8 +39,6 @@ final class Covers extends Attribute $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversClass({$covering->class}::class)]"; } elseif ($covering instanceof CoversFunction) { $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversFunction('{$covering->function}')]"; - } else { - $attributes[] = "#[\PHPUnit\Framework\Attributes\CoversNothing]"; } } diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index ed3d70e8..7e250eed 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -33,6 +33,7 @@ final class TestCaseFactory private static array $annotations = [ Annotations\Depends::class, Annotations\Groups::class, + Annotations\CoversNothing::class, ]; /** @@ -150,25 +151,31 @@ final class TestCaseFactory $classFQN .= $className; } - $methodsCode = implode('', array_map( - fn (TestCaseMethodFactory $methodFactory) => $methodFactory->buildForEvaluation($classFQN, self::$annotations), - $methods - )); + $classAvailableAttributes = array_filter(self::$attributes, fn (string $attribute) => $attribute::ABOVE_CLASS); + $methodAvailableAttributes = array_filter(self::$attributes, fn (string $attribute) => !$attribute::ABOVE_CLASS); - $classAttributesCode = []; - $classAvailableAttributes = array_filter(self::$attributes, fn (string $attribute) => $attribute::ABOVE_CLASS); + $classAttributes = []; foreach ($classAvailableAttributes as $attribute) { - $classAttributesCode = array_reduce( + $classAttributes = array_reduce( $methods, fn (array $carry, TestCaseMethodFactory $methodFactory) => (new $attribute())->__invoke($methodFactory, $carry), - $classAttributesCode + $classAttributes ); } + $methodsCode = implode('', array_map( + fn (TestCaseMethodFactory $methodFactory) => $methodFactory->buildForEvaluation( + $classFQN, + self::$annotations, + $methodAvailableAttributes + ), + $methods + )); + $classAttributesCode = implode('', array_map( - static fn (string $attribute) => sprintf("\n %s", $attribute), - array_unique($classAttributesCode), + static fn (string $attribute) => sprintf("\n %s", $attribute), + array_unique($classAttributes), )); try { diff --git a/src/Factories/TestCaseMethodFactory.php b/src/Factories/TestCaseMethodFactory.php index 21118b8f..83c6678d 100644 --- a/src/Factories/TestCaseMethodFactory.php +++ b/src/Factories/TestCaseMethodFactory.php @@ -114,8 +114,9 @@ final class TestCaseMethodFactory * Creates a PHPUnit method as a string ready for evaluation. * * @param array $annotationsToUse + * @param array> $attributesToUse */ - public function buildForEvaluation(string $classFQN, array $annotationsToUse): string + public function buildForEvaluation(string $classFQN, array $annotationsToUse, array $attributesToUse): string { if ($this->description === null) { throw ShouldNotHappen::fromMessage('The test description may not be empty.'); @@ -129,12 +130,18 @@ final class TestCaseMethodFactory $datasetsCode = ''; $annotations = ['@test']; + $attributes = []; foreach ($annotationsToUse as $annotation) { /** @phpstan-ignore-next-line */ $annotations = (new $annotation())->__invoke($this, $annotations); } + foreach ($attributesToUse as $attribute) { + /** @phpstan-ignore-next-line */ + $attributes = (new $attribute())->__invoke($this, $attributes); + } + if (count($this->datasets) > 0) { $dataProviderName = $methodName . '_dataset'; $annotations[] = "@dataProvider $dataProviderName"; @@ -145,10 +152,15 @@ final class TestCaseMethodFactory static fn ($annotation) => sprintf("\n * %s", $annotation), $annotations, )); + $attributes = implode('', array_map( + static fn ($attribute) => sprintf("\n %s", $attribute), $attributes, + )); + return <<__runTest( diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index bc125599..48f612b8 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -224,7 +224,7 @@ final class TestCall */ public function coversNothing(): TestCall { - $this->testCaseMethod->covers[] = new CoversNothing(); + $this->testCaseMethod->covers = [new CoversNothing()]; return $this; } diff --git a/tests/Features/Covers.php b/tests/Features/Covers.php index 3b9d6809..63c3d8a1 100644 --- a/tests/Features/Covers.php +++ b/tests/Features/Covers.php @@ -35,37 +35,42 @@ it('uses the correct PHPUnit attribute for function', function () { expect($attributes[1]->getArguments()[0])->toBe('foo'); })->coversFunction('foo'); -it('uses the correct PHPUnit attribute for nothing', function () { - $attributes = (new ReflectionClass($this))->getAttributes(); - - expect($attributes[2]->getName())->toBe('PHPUnit\Framework\Attributes\CoversNothing'); -})->coversNothing(); - it('removes duplicated attributes', function () { $attributes = (new ReflectionClass($this))->getAttributes(); + expect($attributes[2]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); + expect($attributes[2]->getArguments()[0])->toBe('P\Tests\Features\TestCoversClass2'); expect($attributes[3]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); - expect($attributes[3]->getArguments()[0])->toBe('P\Tests\Features\TestCoversClass2'); - expect($attributes[4]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); - expect($attributes[4]->getArguments()[0])->toBe('Pest\Factories\Attributes\Covers'); + expect($attributes[3]->getArguments()[0])->toBe('Pest\Factories\Attributes\Covers'); + expect($attributes[4]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); + expect($attributes[4]->getArguments()[0])->toBe('bar'); expect($attributes[5]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); - expect($attributes[5]->getArguments()[0])->toBe('bar'); - expect($attributes[6]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); - expect($attributes[6]->getArguments()[0])->toBe('baz'); + expect($attributes[5]->getArguments()[0])->toBe('baz'); }) ->coversClass(TestCoversClass2::class, TestCoversClass1::class, Covers::class) - ->coversNothing() ->coversFunction('bar', 'foo', 'baz'); it('guesses if the given argument is a class or function', function () { $attributes = (new ReflectionClass($this))->getAttributes(); - expect($attributes[7]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); - expect($attributes[7]->getArguments()[0])->toBe('P\Tests\Features\TestCoversClass3'); - expect($attributes[8]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); - expect($attributes[8]->getArguments()[0])->toBe('testCoversFunction'); + expect($attributes[6]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass'); + expect($attributes[6]->getArguments()[0])->toBe('P\Tests\Features\TestCoversClass3'); + expect($attributes[7]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction'); + expect($attributes[7]->getArguments()[0])->toBe('testCoversFunction'); })->covers(TestCoversClass3::class, 'testCoversFunction'); +it('appends CoversNothing to method attributes', function () { + $phpDoc = (new ReflectionClass($this))->getMethod($this->getName()); + + expect(str_contains($phpDoc->getDocComment(), '* @coversNothing'))->toBeTrue(); +})->coversNothing(); + +it('does not append CoversNothing to other methods', function () { + $phpDoc = (new ReflectionClass($this))->getMethod($this->getName()); + + expect(str_contains($phpDoc->getDocComment(), '* @coversNothing'))->toBeFalse(); +}); + it('throws exception if no class nor method has been found', function () { $testCall = new TestCall(TestSuite::getInstance(), 'filename', 'description', fn () => 'closure'); From 3dc451cf44682df6f7ddcb53fbb6de0f6a921a6b Mon Sep 17 00:00:00 2001 From: danilopolani Date: Wed, 9 Mar 2022 11:08:11 +0100 Subject: [PATCH 29/32] fix typo --- src/Factories/TestCaseFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index 7e250eed..a1ff1cd6 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -37,7 +37,7 @@ final class TestCaseFactory ]; /** - * The list of annotations. + * The list of attributes. * * @var array> */ From 09e2a26b7d117b3557601512856260f591ff673e Mon Sep 17 00:00:00 2001 From: danilopolani Date: Wed, 9 Mar 2022 11:09:03 +0100 Subject: [PATCH 30/32] fix linting --- src/Factories/TestCaseMethodFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Factories/TestCaseMethodFactory.php b/src/Factories/TestCaseMethodFactory.php index 83c6678d..7830b693 100644 --- a/src/Factories/TestCaseMethodFactory.php +++ b/src/Factories/TestCaseMethodFactory.php @@ -113,7 +113,7 @@ final class TestCaseMethodFactory /** * Creates a PHPUnit method as a string ready for evaluation. * - * @param array $annotationsToUse + * @param array $annotationsToUse * @param array> $attributesToUse */ public function buildForEvaluation(string $classFQN, array $annotationsToUse, array $attributesToUse): string From a3889110f12f077a642b1781c2dfb59e39fca70a Mon Sep 17 00:00:00 2001 From: danilopolani Date: Wed, 9 Mar 2022 11:48:35 +0100 Subject: [PATCH 31/32] fix phpstan types --- src/Factories/Attributes/Attribute.php | 12 ++++++++++++ src/Factories/TestCaseMethodFactory.php | 1 - 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Factories/Attributes/Attribute.php b/src/Factories/Attributes/Attribute.php index 22a08968..e53fbe13 100644 --- a/src/Factories/Attributes/Attribute.php +++ b/src/Factories/Attributes/Attribute.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace Pest\Factories\Attributes; +use Pest\Factories\TestCaseMethodFactory; + /** * @internal */ @@ -15,4 +17,14 @@ abstract class Attribute * @var bool */ public const ABOVE_CLASS = false; + + /** + * @param array $attributes + * + * @return array + */ + public function __invoke(TestCaseMethodFactory $method, array $attributes): array // @phpstan-ignore-line + { + return $attributes; + } } diff --git a/src/Factories/TestCaseMethodFactory.php b/src/Factories/TestCaseMethodFactory.php index 7830b693..effd525a 100644 --- a/src/Factories/TestCaseMethodFactory.php +++ b/src/Factories/TestCaseMethodFactory.php @@ -138,7 +138,6 @@ final class TestCaseMethodFactory } foreach ($attributesToUse as $attribute) { - /** @phpstan-ignore-next-line */ $attributes = (new $attribute())->__invoke($this, $attributes); } From fca0c8fc0c3f9395a0969ab92edec179d6e519b4 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Fri, 11 Mar 2022 19:58:21 +0000 Subject: [PATCH 32/32] Adds sponsor --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8727bc84..a5f32bcf 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ We would like to extend our thanks to the following sponsors for funding Pest de ### Platinum Sponsors +- **[Advent](https://advent.dev)** - **[Spatie](https://spatie.be)** - **[Worksome](https://www.worksome.com/)**