From def77dad1e483259dbcdd91016568ad97daf7248 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 15:21:20 +0400 Subject: [PATCH 01/18] chore: Update metafiles --- .gitattributes | 17 ++++++++++------- .gitignore | 8 +++++++- phpunit.xml.legacy | 30 ------------------------------ 3 files changed, 17 insertions(+), 38 deletions(-) delete mode 100644 phpunit.xml.legacy diff --git a/.gitattributes b/.gitattributes index 5d5606d..7104267 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,10 @@ -/.gitattributes export-ignore -/.github/ export-ignore -/.gitignore export-ignore -/phpstan.neon.dist export-ignore -/phpunit.xml.dist export-ignore -/phpunit.xml.legacy export-ignore -/tests/ export-ignore +* text=auto + +/.* export-ignore +/tests export-ignore +/phpunit.xml* export-ignore +/psalm.* export-ignore +/psalm-baseline.xml export-ignore +/infection.* export-ignore +/rector.php export-ignore +/phpstan.* export-ignore diff --git a/.gitignore b/.gitignore index c8153b5..99dd26d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ -/composer.lock +/.* +!/.github/ +!/.php-cs-fixer.dist.php +/runtime/ /vendor/ +/.env +/composer.lock +*.log diff --git a/phpunit.xml.legacy b/phpunit.xml.legacy deleted file mode 100644 index 0dacab1..0000000 --- a/phpunit.xml.legacy +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - ./tests/ - ./tests/ - - - - - ./src/ - - ./src/functions_include.php - - - - - - - - - - - - From c5040c0c89661c347099541d0d043aa35cdc7cb5 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 15:23:02 +0400 Subject: [PATCH 02/18] refactor: Drop supporting old PHP versions; configure composer.json --- .github/workflows/ci.yml | 9 ------ composer.json | 29 +++++++++++++---- tests/PromiseTest.php | 70 ---------------------------------------- 3 files changed, 23 insertions(+), 85 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7761a8..1b3f223 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,11 +15,6 @@ jobs: - 8.3 - 8.2 - 8.1 - - 8.0 - - 7.4 - - 7.3 - - 7.2 - - 7.1 steps: - uses: actions/checkout@v5 - uses: shivammathur/setup-php@v2 @@ -43,10 +38,6 @@ jobs: - 8.3 - 8.2 - 8.1 - - 8.0 - - 7.4 - - 7.3 - - 7.2 steps: - uses: actions/checkout@v5 - uses: shivammathur/setup-php@v2 diff --git a/composer.json b/composer.json index 6bf687d..a163c2a 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,11 @@ { - "name": "react/promise", + "name": "internal/promise", "description": "A lightweight implementation of CommonJS Promises/A for PHP", "license": "MIT", + "keywords": [ + "promise", + "promises" + ], "authors": [ { "name": "Jan Sorgalla", @@ -25,7 +29,10 @@ } ], "require": { - "php": ">=7.1.0" + "php": ">=8.1.0" + }, + "replace": { + "react/promise": "^3.0" }, "require-dev": { "phpstan/phpstan": "1.12.28 || 1.4.10", @@ -50,8 +57,18 @@ "tests/Fiber.php" ] }, - "keywords": [ - "promise", - "promises" - ] + "config": { + "audit": { + "abandoned": "report" + }, + "sort-packages": true + }, + "scripts": { + "stan": "stan", + "test": "phpunit --color=always --testdox", + "test:cc": [ + "@putenv XDEBUG_MODE=coverage", + "phpunit --coverage-clover=runtime/phpunit/logs/clover.xml --color=always" + ] + } } diff --git a/tests/PromiseTest.php b/tests/PromiseTest.php index a0e9ace..d097b90 100644 --- a/tests/PromiseTest.php +++ b/tests/PromiseTest.php @@ -139,76 +139,6 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio $this->assertSame(0, gc_collect_cycles()); } - /** - * Test that checks number of garbage cycles after throwing from a canceller - * that explicitly uses a reference to the promise. This is rather synthetic, - * actual use cases often have implicit (hidden) references which ought not - * to be stored in the stack trace. - * - * Reassigned arguments only show up in the stack trace in PHP 7, so we can't - * avoid this on legacy PHP. As an alternative, consider explicitly unsetting - * any references before throwing. - * - * @test - * @requires PHP 7 - */ - public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException(): void - { - gc_collect_cycles(); - /** @var Promise $promise */ - $promise = new Promise(function () {}, function () use (&$promise) { - assert($promise instanceof Promise); - throw new \Exception('foo'); - }); - $promise->cancel(); - unset($promise); - - $this->assertSame(0, gc_collect_cycles()); - } - - /** - * @test - * @requires PHP 7 - * @see self::shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException - */ - public function shouldRejectWithoutCreatingGarbageCyclesIfResolverWithReferenceThrowsException(): void - { - gc_collect_cycles(); - /** @var Promise $promise */ - $promise = new Promise(function () use (&$promise) { - assert($promise instanceof Promise); - throw new \Exception('foo'); - }); - - $promise->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection - - unset($promise); - - $this->assertSame(0, gc_collect_cycles()); - } - - /** - * @test - * @requires PHP 7 - * @see self::shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException - */ - public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenceAndResolverThrowsException(): void - { - gc_collect_cycles(); - /** @var Promise $promise */ - $promise = new Promise(function () { - throw new \Exception('foo'); - }, function () use (&$promise) { - assert($promise instanceof Promise); - }); - - $promise->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection - - unset($promise); - - $this->assertSame(0, gc_collect_cycles()); - } - /** @test */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise(): void { From 538985853fb71f42ee7b3fab69a16b5795095bb2 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 15:54:21 +0400 Subject: [PATCH 03/18] docs: Add `@yield` annotation to `PromiseInterface` --- src/PromiseInterface.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PromiseInterface.php b/src/PromiseInterface.php index 5869f76..34f3669 100644 --- a/src/PromiseInterface.php +++ b/src/PromiseInterface.php @@ -3,6 +3,7 @@ namespace React\Promise; /** + * @yield T * @template-covariant T */ interface PromiseInterface From 51c1173236b3d2c90020207785d0e8703f6936aa Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 16:09:27 +0400 Subject: [PATCH 04/18] fix: Make rejection handlers reusable; remove `exit(255)` from RejectionPromise; --- composer.json | 2 +- src/Internal/RejectedPromise.php | 29 ++++++++++------------------- src/functions.php | 7 +++++-- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/composer.json b/composer.json index a163c2a..61ef792 100644 --- a/composer.json +++ b/composer.json @@ -64,7 +64,7 @@ "sort-packages": true }, "scripts": { - "stan": "stan", + "stan": "phpstan", "test": "phpunit --color=always --testdox", "test:cc": [ "@putenv XDEBUG_MODE=coverage", diff --git a/src/Internal/RejectedPromise.php b/src/Internal/RejectedPromise.php index aa1dff3..d8a922b 100644 --- a/src/Internal/RejectedPromise.php +++ b/src/Internal/RejectedPromise.php @@ -14,44 +14,35 @@ */ final class RejectedPromise implements PromiseInterface { - /** @var \Throwable */ - private $reason; + private \Throwable $reason; + private bool $handled = false; + private static ?\Closure $rejectionHandler = null; - /** @var bool */ - private $handled = false; - - /** - * @param \Throwable $reason - */ public function __construct(\Throwable $reason) { $this->reason = $reason; } + public static function setRejectionHandler(?callable $handler): void + { + self::$rejectionHandler = $handler === null ? null : $handler(...); + } + /** @throws void */ public function __destruct() { - if ($this->handled) { - return; - } - - $handler = set_rejection_handler(null); - if ($handler === null) { - $message = 'Unhandled promise rejection with ' . $this->reason; - - \error_log($message); + if ($this->handled || self::$rejectionHandler === null) { return; } try { - $handler($this->reason); + (self::$rejectionHandler)($this->reason); } catch (\Throwable $e) { \preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match); \assert(isset($match[1], $match[2])); $message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2]; \error_log($message); - exit(255); } } diff --git a/src/functions.php b/src/functions.php index 214aad6..32d998f 100644 --- a/src/functions.php +++ b/src/functions.php @@ -249,18 +249,21 @@ function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continu * [`finally()` method](#promiseinterfacefinally). * See also the [`reject()` function](#reject) for more details. * - * @param callable(\Throwable):void|null $callback - * @return callable(\Throwable):void|null + * @param callable(\Throwable):mixed|null $callback + * @return callable(\Throwable):mixed|null */ function set_rejection_handler(?callable $callback): ?callable { static $current = null; $previous = $current; $current = $callback; + RejectedPromise::setRejectionHandler($current); return $previous; } +set_rejection_handler(static fn(\Throwable $reason) => \error_log('Unhandled promise rejection with ' . $reason)); + /** * @internal */ From 6a4c0bf947e1275b030bcc803d13247239e22613 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 16:12:15 +0400 Subject: [PATCH 05/18] docs: Update readme, separate documentation --- README.md | 732 +++-------------------------------------------- documentation.md | 641 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 674 insertions(+), 699 deletions(-) create mode 100644 documentation.md diff --git a/README.md b/README.md index 2108d98..1e84dc0 100644 --- a/README.md +++ b/README.md @@ -1,722 +1,56 @@ -Promise -======= +# Promise -A lightweight implementation of -[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP. +A lightweight implementation of [CommonJS Promises/A][CommonJS Promises/A] for PHP. -[![CI status](https://github.com/reactphp/promise/workflows/CI/badge.svg)](https://github.com/reactphp/promise/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/promise?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/promise) +> [!NOTE] +> This is a fork of [reactphp/promise][reactphp/promise] with the following improvements: +> - PHP 8.1+ +> - `@yield` annotation in the PromiseInterface +> - Replaces `react/promise` v3 +> - Make rejection handler reusable. `error_log()` is still used by default. +> - Removed `exit(255)` from RejectionPromise. -Table of Contents ------------------ - -1. [Introduction](#introduction) -2. [Concepts](#concepts) - * [Deferred](#deferred) - * [Promise](#promise-1) -3. [API](#api) - * [Deferred](#deferred-1) - * [Deferred::promise()](#deferredpromise) - * [Deferred::resolve()](#deferredresolve) - * [Deferred::reject()](#deferredreject) - * [PromiseInterface](#promiseinterface) - * [PromiseInterface::then()](#promiseinterfacethen) - * [PromiseInterface::catch()](#promiseinterfacecatch) - * [PromiseInterface::finally()](#promiseinterfacefinally) - * [PromiseInterface::cancel()](#promiseinterfacecancel) - * [~~PromiseInterface::otherwise()~~](#promiseinterfaceotherwise) - * [~~PromiseInterface::always()~~](#promiseinterfacealways) - * [Promise](#promise-2) - * [Functions](#functions) - * [resolve()](#resolve) - * [reject()](#reject) - * [all()](#all) - * [race()](#race) - * [any()](#any) - * [set_rejection_handler()](#set_rejection_handler) -4. [Examples](#examples) - * [How to use Deferred](#how-to-use-deferred) - * [How promise forwarding works](#how-promise-forwarding-works) - * [Resolution forwarding](#resolution-forwarding) - * [Rejection forwarding](#rejection-forwarding) - * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding) -5. [Install](#install) -6. [Tests](#tests) -7. [Credits](#credits) -8. [License](#license) - -Introduction ------------- - -Promise is a library implementing -[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP. - -It also provides several other useful promise-related concepts, such as joining -multiple promises and mapping and reducing collections of promises. - -If you've never heard about promises before, -[read this first](https://gist.github.com/domenic/3889970). - -Concepts --------- - -### Deferred - -A **Deferred** represents a computation or unit of work that may not have -completed yet. Typically (but not always), that computation will be something -that executes asynchronously and completes at some point in the future. - -### Promise - -While a deferred represents the computation itself, a **Promise** represents -the result of that computation. Thus, each deferred has a promise that acts as -a placeholder for its actual result. - -API ---- - -### Deferred - -A deferred represents an operation whose resolution is pending. It has separate -promise and resolver parts. - -```php -$deferred = new React\Promise\Deferred(); - -$promise = $deferred->promise(); - -$deferred->resolve(mixed $value); -$deferred->reject(\Throwable $reason); -``` - -The `promise` method returns the promise of the deferred. - -The `resolve` and `reject` methods control the state of the deferred. - -The constructor of the `Deferred` accepts an optional `$canceller` argument. -See [Promise](#promise-2) for more information. - -#### Deferred::promise() - -```php -$promise = $deferred->promise(); -``` - -Returns the promise of the deferred, which you can hand out to others while -keeping the authority to modify its state to yourself. - -#### Deferred::resolve() - -```php -$deferred->resolve(mixed $value); -``` - -Resolves the promise returned by `promise()`. All consumers are notified by -having `$onFulfilled` (which they registered via `$promise->then()`) called with -`$value`. - -If `$value` itself is a promise, the promise will transition to the state of -this promise once it is resolved. - -See also the [`resolve()` function](#resolve). - -#### Deferred::reject() - -```php -$deferred->reject(\Throwable $reason); -``` - -Rejects the promise returned by `promise()`, signalling that the deferred's -computation failed. -All consumers are notified by having `$onRejected` (which they registered via -`$promise->then()`) called with `$reason`. - -See also the [`reject()` function](#reject). - -### PromiseInterface - -The promise interface provides the common interface for all promise -implementations. -See [Promise](#promise-2) for the only public implementation exposed by this -package. - -A promise represents an eventual outcome, which is either fulfillment (success) -and an associated value, or rejection (failure) and an associated reason. - -Once in the fulfilled or rejected state, a promise becomes immutable. -Neither its state nor its result (or error) can be modified. - -#### PromiseInterface::then() - -```php -$transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null); -``` - -Transforms a promise's value by applying a function to the promise's fulfillment -or rejection value. Returns a new promise for the transformed result. - -The `then()` method registers new fulfilled and rejection handlers with a promise -(all parameters are optional): - - * `$onFulfilled` will be invoked once the promise is fulfilled and passed - the result as the first argument. - * `$onRejected` will be invoked once the promise is rejected and passed the - reason as the first argument. - -It returns a new promise that will fulfill with the return value of either -`$onFulfilled` or `$onRejected`, whichever is called, or will reject with -the thrown exception if either throws. - -A promise makes the following guarantees about handlers registered in -the same call to `then()`: - - 1. Only one of `$onFulfilled` or `$onRejected` will be called, - never both. - 2. `$onFulfilled` and `$onRejected` will never be called more - than once. - -#### See also - -* [resolve()](#resolve) - Creating a resolved promise -* [reject()](#reject) - Creating a rejected promise - -#### PromiseInterface::catch() - -```php -$promise->catch(callable $onRejected); -``` - -Registers a rejection handler for promise. It is a shortcut for: - -```php -$promise->then(null, $onRejected); -``` - -Additionally, you can type hint the `$reason` argument of `$onRejected` to catch -only specific errors. - -```php -$promise - ->catch(function (\RuntimeException $reason) { - // Only catch \RuntimeException instances - // All other types of errors will propagate automatically - }) - ->catch(function (\Throwable $reason) { - // Catch other errors - }); -``` - -#### PromiseInterface::finally() - -```php -$newPromise = $promise->finally(callable $onFulfilledOrRejected); -``` - -Allows you to execute "cleanup" type tasks in a promise chain. - -It arranges for `$onFulfilledOrRejected` to be called, with no arguments, -when the promise is either fulfilled or rejected. - -* If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully, - `$newPromise` will fulfill with the same value as `$promise`. -* If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a - rejected promise, `$newPromise` will reject with the thrown exception or - rejected promise's reason. -* If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully, - `$newPromise` will reject with the same reason as `$promise`. -* If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a - rejected promise, `$newPromise` will reject with the thrown exception or - rejected promise's reason. - -`finally()` behaves similarly to the synchronous finally statement. When combined -with `catch()`, `finally()` allows you to write code that is similar to the familiar -synchronous catch/finally pair. - -Consider the following synchronous code: - -```php -try { - return doSomething(); -} catch (\Throwable $e) { - return handleError($e); -} finally { - cleanup(); -} -``` - -Similar asynchronous code (with `doSomething()` that returns a promise) can be -written: - -```php -return doSomething() - ->catch('handleError') - ->finally('cleanup'); -``` - -#### PromiseInterface::cancel() - -``` php -$promise->cancel(); -``` - -The `cancel()` method notifies the creator of the promise that there is no -further interest in the results of the operation. - -Once a promise is settled (either fulfilled or rejected), calling `cancel()` on -a promise has no effect. - -#### ~~PromiseInterface::otherwise()~~ - -> Deprecated since v3.0.0, see [`catch()`](#promiseinterfacecatch) instead. - -The `otherwise()` method registers a rejection handler for a promise. - -This method continues to exist only for BC reasons and to ease upgrading -between versions. It is an alias for: - -```php -$promise->catch($onRejected); -``` - -#### ~~PromiseInterface::always()~~ - -> Deprecated since v3.0.0, see [`finally()`](#promiseinterfacefinally) instead. - -The `always()` method allows you to execute "cleanup" type tasks in a promise chain. - -This method continues to exist only for BC reasons and to ease upgrading -between versions. It is an alias for: - -```php -$promise->finally($onFulfilledOrRejected); -``` - -### Promise - -Creates a promise whose state is controlled by the functions passed to -`$resolver`. - -```php -$resolver = function (callable $resolve, callable $reject) { - // Do some work, possibly asynchronously, and then - // resolve or reject. - - $resolve($awesomeResult); - // or throw new Exception('Promise rejected'); - // or $resolve($anotherPromise); - // or $reject($nastyError); -}; - -$canceller = function () { - // Cancel/abort any running operations like network connections, streams etc. - - // Reject promise by throwing an exception - throw new Exception('Promise cancelled'); -}; - -$promise = new React\Promise\Promise($resolver, $canceller); -``` - -The promise constructor receives a resolver function and an optional canceller -function which both will be called with two arguments: - - * `$resolve($value)` - Primary function that seals the fate of the - returned promise. Accepts either a non-promise value, or another promise. - When called with a non-promise value, fulfills promise with that value. - When called with another promise, e.g. `$resolve($otherPromise)`, promise's - fate will be equivalent to that of `$otherPromise`. - * `$reject($reason)` - Function that rejects the promise. It is recommended to - just throw an exception instead of using `$reject()`. - -If the resolver or canceller throw an exception, the promise will be rejected -with that thrown exception as the rejection reason. - -The resolver function will be called immediately, the canceller function only -once all consumers called the `cancel()` method of the promise. - -### Functions - -Useful functions for creating and joining collections of promises. - -All functions working on promise collections (like `all()`, `race()`, -etc.) support cancellation. This means, if you call `cancel()` on the returned -promise, all promises in the collection are cancelled. - -#### resolve() - -```php -$promise = React\Promise\resolve(mixed $promiseOrValue); -``` - -Creates a promise for the supplied `$promiseOrValue`. - -If `$promiseOrValue` is a value, it will be the resolution value of the -returned promise. - -If `$promiseOrValue` is a thenable (any object that provides a `then()` method), -a trusted promise that follows the state of the thenable is returned. - -If `$promiseOrValue` is a promise, it will be returned as is. - -The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface) -and can be consumed like any other promise: - -```php -$promise = React\Promise\resolve(42); - -$promise->then(function (int $result): void { - var_dump($result); -}, function (\Throwable $e): void { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -#### reject() - -```php -$promise = React\Promise\reject(\Throwable $reason); -``` - -Creates a rejected promise for the supplied `$reason`. - -Note that the [`\Throwable`](https://www.php.net/manual/en/class.throwable.php) interface introduced in PHP 7 covers -both user land [`\Exception`](https://www.php.net/manual/en/class.exception.php)'s and -[`\Error`](https://www.php.net/manual/en/class.error.php) internal PHP errors. By enforcing `\Throwable` as reason to -reject a promise, any language error or user land exception can be used to reject a promise. - -The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface) -and can be consumed like any other promise: - -```php -$promise = React\Promise\reject(new RuntimeException('Request failed')); - -$promise->then(function (int $result): void { - var_dump($result); -}, function (\Throwable $e): void { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); -``` - -Note that rejected promises should always be handled similar to how any -exceptions should always be caught in a `try` + `catch` block. If you remove the -last reference to a rejected promise that has not been handled, it will -report an unhandled promise rejection: - -```php -function incorrect(): int -{ - $promise = React\Promise\reject(new RuntimeException('Request failed')); - - // Commented out: No rejection handler registered here. - // $promise->then(null, function (\Throwable $e): void { /* ignore */ }); - - // Returning from a function will remove all local variable references, hence why - // this will report an unhandled promise rejection here. - return 42; -} - -// Calling this function will log an error message plus its stack trace: -// Unhandled promise rejection with RuntimeException: Request failed in example.php:10 -incorrect(); -``` - -A rejected promise will be considered "handled" if you catch the rejection -reason with either the [`then()` method](#promiseinterfacethen), the -[`catch()` method](#promiseinterfacecatch), or the -[`finally()` method](#promiseinterfacefinally). Note that each of these methods -return a new promise that may again be rejected if you re-throw an exception. - -A rejected promise will also be considered "handled" if you abort the operation -with the [`cancel()` method](#promiseinterfacecancel) (which in turn would -usually reject the promise if it is still pending). - -See also the [`set_rejection_handler()` function](#set_rejection_handler). - -#### all() - -```php -$promise = React\Promise\all(iterable $promisesOrValues); -``` - -Returns a promise that will resolve only once all the items in -`$promisesOrValues` have resolved. The resolution value of the returned promise -will be an array containing the resolution values of each of the items in -`$promisesOrValues`. - -#### race() - -```php -$promise = React\Promise\race(iterable $promisesOrValues); -``` - -Initiates a competitive race that allows one winner. Returns a promise which is -resolved in the same way the first settled promise resolves. - -The returned promise will become **infinitely pending** if `$promisesOrValues` -contains 0 items. - -#### any() - -```php -$promise = React\Promise\any(iterable $promisesOrValues); -``` - -Returns a promise that will resolve when any one of the items in -`$promisesOrValues` resolves. The resolution value of the returned promise -will be the resolution value of the triggering item. - -The returned promise will only reject if *all* items in `$promisesOrValues` are -rejected. The rejection value will be a `React\Promise\Exception\CompositeException` -which holds all rejection reasons. The rejection reasons can be obtained with -`CompositeException::getThrowables()`. - -The returned promise will also reject with a `React\Promise\Exception\LengthException` -if `$promisesOrValues` contains 0 items. - -#### set_rejection_handler() - -```php -React\Promise\set_rejection_handler(?callable $callback): ?callable; -``` - -Sets the global rejection handler for unhandled promise rejections. - -Note that rejected promises should always be handled similar to how any -exceptions should always be caught in a `try` + `catch` block. If you remove -the last reference to a rejected promise that has not been handled, it will -report an unhandled promise rejection. See also the [`reject()` function](#reject) -for more details. - -The `?callable $callback` argument MUST be a valid callback function that -accepts a single `Throwable` argument or a `null` value to restore the -default promise rejection handler. The return value of the callback function -will be ignored and has no effect, so you SHOULD return a `void` value. The -callback function MUST NOT throw or the program will be terminated with a -fatal error. - -The function returns the previous rejection handler or `null` if using the -default promise rejection handler. - -The default promise rejection handler will log an error message plus its stack -trace: - -```php -// Unhandled promise rejection with RuntimeException: Unhandled in example.php:2 -React\Promise\reject(new RuntimeException('Unhandled')); -``` - -The promise rejection handler may be used to use customize the log message or -write to custom log targets. As a rule of thumb, this function should only be -used as a last resort and promise rejections are best handled with either the -[`then()` method](#promiseinterfacethen), the -[`catch()` method](#promiseinterfacecatch), or the -[`finally()` method](#promiseinterfacefinally). -See also the [`reject()` function](#reject) for more details. - -Examples --------- - -### How to use Deferred - -```php -function getAwesomeResultPromise() -{ - $deferred = new React\Promise\Deferred(); - - // Execute a Node.js-style function using the callback pattern - computeAwesomeResultAsynchronously(function (\Throwable $error, $result) use ($deferred) { - if ($error) { - $deferred->reject($error); - } else { - $deferred->resolve($result); - } - }); - - // Return the promise - return $deferred->promise(); -} - -getAwesomeResultPromise() - ->then( - function ($value) { - // Deferred resolved, do something with $value - }, - function (\Throwable $reason) { - // Deferred rejected, do something with $reason - } - ); -``` - -### How promise forwarding works - -A few simple examples to show how the mechanics of Promises/A forwarding works. -These examples are contrived, of course, and in real usage, promise chains will -typically be spread across several function calls, or even several levels of -your application architecture. - -#### Resolution forwarding - -Resolved promises forward resolution values to the next promise. -The first promise, `$deferred->promise()`, will resolve with the value passed -to `$deferred->resolve()` below. - -Each call to `then()` returns a new promise that will resolve with the return -value of the previous handler. This creates a promise "pipeline". - -```php -$deferred = new React\Promise\Deferred(); - -$deferred->promise() - ->then(function ($x) { - // $x will be the value passed to $deferred->resolve() below - // and returns a *new promise* for $x + 1 - return $x + 1; - }) - ->then(function ($x) { - // $x === 2 - // This handler receives the return value of the - // previous handler. - return $x + 1; - }) - ->then(function ($x) { - // $x === 3 - // This handler receives the return value of the - // previous handler. - return $x + 1; - }) - ->then(function ($x) { - // $x === 4 - // This handler receives the return value of the - // previous handler. - echo 'Resolve ' . $x; - }); - -$deferred->resolve(1); // Prints "Resolve 4" -``` - -#### Rejection forwarding - -Rejected promises behave similarly, and also work similarly to try/catch: -When you catch an exception, you must rethrow for it to propagate. - -Similarly, when you handle a rejected promise, to propagate the rejection, -"rethrow" it by either returning a rejected promise, or actually throwing -(since promise translates thrown exceptions into rejections) - -```php -$deferred = new React\Promise\Deferred(); - -$deferred->promise() - ->then(function ($x) { - throw new \Exception($x + 1); - }) - ->catch(function (\Exception $x) { - // Propagate the rejection - throw $x; - }) - ->catch(function (\Exception $x) { - // Can also propagate by returning another rejection - return React\Promise\reject( - new \Exception($x->getMessage() + 1) - ); - }) - ->catch(function ($x) { - echo 'Reject ' . $x->getMessage(); // 3 - }); - -$deferred->resolve(1); // Prints "Reject 3" -``` - -#### Mixed resolution and rejection forwarding - -Just like try/catch, you can choose to propagate or not. Mixing resolutions and -rejections will still forward handler results in a predictable way. - -```php -$deferred = new React\Promise\Deferred(); - -$deferred->promise() - ->then(function ($x) { - return $x + 1; - }) - ->then(function ($x) { - throw new \Exception($x + 1); - }) - ->catch(function (\Exception $x) { - // Handle the rejection, and don't propagate. - // This is like catch without a rethrow - return $x->getMessage() + 1; - }) - ->then(function ($x) { - echo 'Mixed ' . $x; // 4 - }); - -$deferred->resolve(1); // Prints "Mixed 4" -``` - -Install -------- - -The recommended way to install this library is [through Composer](https://getcomposer.org/). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) - -This project follows [SemVer](https://semver.org/). -This will install the latest supported version from this branch: +## Install ```bash -composer require react/promise:^3.2 +composer require internal/promise ``` -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. - -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on PHP 7.1 through current PHP 8+. -It's *highly recommended to use the latest supported PHP version* for this project. - -We're committed to providing long-term support (LTS) options and to provide a -smooth upgrade path. If you're using an older PHP version, you may use the -[`2.x` branch](https://github.com/reactphp/promise/tree/2.x) (PHP 5.4+) or -[`1.x` branch](https://github.com/reactphp/promise/tree/1.x) (PHP 5.3+) which both -provide a compatible API but do not take advantage of newer language features. -You may target multiple versions at the same time to support a wider range of -PHP versions like this: - -```bash -composer require "react/promise:^3 || ^2 || ^1" -``` +[![PHP](https://img.shields.io/packagist/php-v/internal/promise.svg?style=flat-square&logo=php)](https://packagist.org/packages/internal/promise) +[![Latest Version on Packagist](https://img.shields.io/packagist/v/internal/promise.svg?style=flat-square&logo=packagist)](https://packagist.org/packages/internal/promise) +[![License](https://img.shields.io/packagist/l/internal/promise.svg?style=flat-square)](LICENSE.md) +[![Total Downloads](https://img.shields.io/packagist/dt/internal/promise.svg?style=flat-square)](https://packagist.org/packages/buggregator/trap) ## Tests -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org/): - -```bash -composer install -``` - To run the test suite, go to the project root and run: ```bash -vendor/bin/phpunit +composer test ``` On top of this, we use PHPStan on max level to ensure type safety across the project: ```bash -vendor/bin/phpstan +composer stan ``` -Credits -------- - -Promise is a port of [when.js](https://github.com/cujojs/when) -by [Brian Cavalier](https://github.com/briancavalier). +## Credits -Also, large parts of the documentation have been ported from the when.js -[Wiki](https://github.com/cujojs/when/wiki) and the -[API docs](https://github.com/cujojs/when/blob/master/docs/api.md). +This fork is based on [reactphp/promise][reactphp/promise], which is a port of [when.js][when.js] +by [Brian Cavalier][Brian Cavalier]. -License -------- +Also, large parts of the [documentation][documentation] have been ported from the when.js +[Wiki][Wiki] and the +[API docs][API docs]. -Released under the [MIT](LICENSE) license. +[documentation]: documentation.md +[CommonJS Promises/A]: http://wiki.commonjs.org/wiki/Promises/A +[CI status]: https://img.shields.io/github/actions/workflow/status/internal/promise/ci.yml?branch=2.x +[CI status link]: https://github.com/internal/promise/actions +[installs]: https://img.shields.io/packagist/dt/internal/promise?color=blue&label=installs%20on%20Packagist +[packagist link]: https://packagist.org/packages/internal/promise +[Composer]: https://getcomposer.org +[when.js]: https://github.com/cujojs/when +[Brian Cavalier]: https://github.com/briancavalier +[reactphp/promise]: https://github.com/reactphp/promise diff --git a/documentation.md b/documentation.md new file mode 100644 index 0000000..37bcd04 --- /dev/null +++ b/documentation.md @@ -0,0 +1,641 @@ +# Promise + +A lightweight implementation of [CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP. + +## Table of Contents + +1. [Introduction](#introduction) +2. [Concepts](#concepts) + * [Deferred](#deferred) + * [Promise](#promise-1) +3. [API](#api) + * [Deferred](#deferred-1) + * [Deferred::promise()](#deferredpromise) + * [Deferred::resolve()](#deferredresolve) + * [Deferred::reject()](#deferredreject) + * [PromiseInterface](#promiseinterface) + * [PromiseInterface::then()](#promiseinterfacethen) + * [PromiseInterface::catch()](#promiseinterfacecatch) + * [PromiseInterface::finally()](#promiseinterfacefinally) + * [PromiseInterface::cancel()](#promiseinterfacecancel) + * [~~PromiseInterface::otherwise()~~](#promiseinterfaceotherwise) + * [~~PromiseInterface::always()~~](#promiseinterfacealways) + * [Promise](#promise-2) + * [Functions](#functions) + * [resolve()](#resolve) + * [reject()](#reject) + * [all()](#all) + * [race()](#race) + * [any()](#any) + * [set_rejection_handler()](#set_rejection_handler) +4. [Examples](#examples) + * [How to use Deferred](#how-to-use-deferred) + * [How promise forwarding works](#how-promise-forwarding-works) + * [Resolution forwarding](#resolution-forwarding) + * [Rejection forwarding](#rejection-forwarding) + * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding) + +## Introduction + +Promise is a library implementing +[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP. + +It also provides several other useful promise-related concepts, such as joining +multiple promises and mapping and reducing collections of promises. + +If you've never heard about promises before, +[read this first](https://gist.github.com/domenic/3889970). + +## Concepts + +### Deferred + +A **Deferred** represents a computation or unit of work that may not have +completed yet. Typically (but not always), that computation will be something +that executes asynchronously and completes at some point in the future. + +### Promise + +While a deferred represents the computation itself, a **Promise** represents +the result of that computation. Thus, each deferred has a promise that acts as +a placeholder for its actual result. + +## API + +### Deferred + +A deferred represents an operation whose resolution is pending. It has separate +promise and resolver parts. + +```php +$deferred = new React\Promise\Deferred(); + +$promise = $deferred->promise(); + +$deferred->resolve(mixed $value); +$deferred->reject(\Throwable $reason); +``` + +The `promise` method returns the promise of the deferred. + +The `resolve` and `reject` methods control the state of the deferred. + +The constructor of the `Deferred` accepts an optional `$canceller` argument. +See [Promise](#promise-2) for more information. + +#### Deferred::promise() + +```php +$promise = $deferred->promise(); +``` + +Returns the promise of the deferred, which you can hand out to others while +keeping the authority to modify its state to yourself. + +#### Deferred::resolve() + +```php +$deferred->resolve(mixed $value); +``` + +Resolves the promise returned by `promise()`. All consumers are notified by +having `$onFulfilled` (which they registered via `$promise->then()`) called with +`$value`. + +If `$value` itself is a promise, the promise will transition to the state of +this promise once it is resolved. + +See also the [`resolve()` function](#resolve). + +#### Deferred::reject() + +```php +$deferred->reject(\Throwable $reason); +``` + +Rejects the promise returned by `promise()`, signalling that the deferred's +computation failed. +All consumers are notified by having `$onRejected` (which they registered via +`$promise->then()`) called with `$reason`. + +See also the [`reject()` function](#reject). + +### PromiseInterface + +The promise interface provides the common interface for all promise +implementations. +See [Promise](#promise-2) for the only public implementation exposed by this +package. + +A promise represents an eventual outcome, which is either fulfillment (success) +and an associated value, or rejection (failure) and an associated reason. + +Once in the fulfilled or rejected state, a promise becomes immutable. +Neither its state nor its result (or error) can be modified. + +#### PromiseInterface::then() + +```php +$transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null); +``` + +Transforms a promise's value by applying a function to the promise's fulfillment +or rejection value. Returns a new promise for the transformed result. + +The `then()` method registers new fulfilled and rejection handlers with a promise +(all parameters are optional): + +* `$onFulfilled` will be invoked once the promise is fulfilled and passed + the result as the first argument. +* `$onRejected` will be invoked once the promise is rejected and passed the + reason as the first argument. + +It returns a new promise that will fulfill with the return value of either +`$onFulfilled` or `$onRejected`, whichever is called, or will reject with +the thrown exception if either throws. + +A promise makes the following guarantees about handlers registered in +the same call to `then()`: + +1. Only one of `$onFulfilled` or `$onRejected` will be called, + never both. +2. `$onFulfilled` and `$onRejected` will never be called more + than once. + +#### See also + +* [resolve()](#resolve) - Creating a resolved promise +* [reject()](#reject) - Creating a rejected promise + +#### PromiseInterface::catch() + +```php +$promise->catch(callable $onRejected); +``` + +Registers a rejection handler for promise. It is a shortcut for: + +```php +$promise->then(null, $onRejected); +``` + +Additionally, you can type hint the `$reason` argument of `$onRejected` to catch +only specific errors. + +```php +$promise + ->catch(function (\RuntimeException $reason) { + // Only catch \RuntimeException instances + // All other types of errors will propagate automatically + }) + ->catch(function (\Throwable $reason) { + // Catch other errors + }); +``` + +#### PromiseInterface::finally() + +```php +$newPromise = $promise->finally(callable $onFulfilledOrRejected); +``` + +Allows you to execute "cleanup" type tasks in a promise chain. + +It arranges for `$onFulfilledOrRejected` to be called, with no arguments, +when the promise is either fulfilled or rejected. + +* If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully, + `$newPromise` will fulfill with the same value as `$promise`. +* If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a + rejected promise, `$newPromise` will reject with the thrown exception or + rejected promise's reason. +* If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully, + `$newPromise` will reject with the same reason as `$promise`. +* If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a + rejected promise, `$newPromise` will reject with the thrown exception or + rejected promise's reason. + +`finally()` behaves similarly to the synchronous finally statement. When combined +with `catch()`, `finally()` allows you to write code that is similar to the familiar +synchronous catch/finally pair. + +Consider the following synchronous code: + +```php +try { + return doSomething(); +} catch (\Throwable $e) { + return handleError($e); +} finally { + cleanup(); +} +``` + +Similar asynchronous code (with `doSomething()` that returns a promise) can be +written: + +```php +return doSomething() + ->catch('handleError') + ->finally('cleanup'); +``` + +#### PromiseInterface::cancel() + +``` php +$promise->cancel(); +``` + +The `cancel()` method notifies the creator of the promise that there is no +further interest in the results of the operation. + +Once a promise is settled (either fulfilled or rejected), calling `cancel()` on +a promise has no effect. + +#### ~~PromiseInterface::otherwise()~~ + +> Deprecated since v3.0.0, see [`catch()`](#promiseinterfacecatch) instead. + +The `otherwise()` method registers a rejection handler for a promise. + +This method continues to exist only for BC reasons and to ease upgrading +between versions. It is an alias for: + +```php +$promise->catch($onRejected); +``` + +#### ~~PromiseInterface::always()~~ + +> Deprecated since v3.0.0, see [`finally()`](#promiseinterfacefinally) instead. + +The `always()` method allows you to execute "cleanup" type tasks in a promise chain. + +This method continues to exist only for BC reasons and to ease upgrading +between versions. It is an alias for: + +```php +$promise->finally($onFulfilledOrRejected); +``` + +### Promise + +Creates a promise whose state is controlled by the functions passed to +`$resolver`. + +```php +$resolver = function (callable $resolve, callable $reject) { + // Do some work, possibly asynchronously, and then + // resolve or reject. + + $resolve($awesomeResult); + // or throw new Exception('Promise rejected'); + // or $resolve($anotherPromise); + // or $reject($nastyError); +}; + +$canceller = function () { + // Cancel/abort any running operations like network connections, streams etc. + + // Reject promise by throwing an exception + throw new Exception('Promise cancelled'); +}; + +$promise = new React\Promise\Promise($resolver, $canceller); +``` + +The promise constructor receives a resolver function and an optional canceller +function which both will be called with two arguments: + +* `$resolve($value)` - Primary function that seals the fate of the + returned promise. Accepts either a non-promise value, or another promise. + When called with a non-promise value, fulfills promise with that value. + When called with another promise, e.g. `$resolve($otherPromise)`, promise's + fate will be equivalent to that of `$otherPromise`. +* `$reject($reason)` - Function that rejects the promise. It is recommended to + just throw an exception instead of using `$reject()`. + +If the resolver or canceller throw an exception, the promise will be rejected +with that thrown exception as the rejection reason. + +The resolver function will be called immediately, the canceller function only +once all consumers called the `cancel()` method of the promise. + +### Functions + +Useful functions for creating and joining collections of promises. + +All functions working on promise collections (like `all()`, `race()`, +etc.) support cancellation. This means, if you call `cancel()` on the returned +promise, all promises in the collection are cancelled. + +#### resolve() + +```php +$promise = React\Promise\resolve(mixed $promiseOrValue); +``` + +Creates a promise for the supplied `$promiseOrValue`. + +If `$promiseOrValue` is a value, it will be the resolution value of the +returned promise. + +If `$promiseOrValue` is a thenable (any object that provides a `then()` method), +a trusted promise that follows the state of the thenable is returned. + +If `$promiseOrValue` is a promise, it will be returned as is. + +The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface) +and can be consumed like any other promise: + +```php +$promise = React\Promise\resolve(42); + +$promise->then(function (int $result): void { + var_dump($result); +}, function (\Throwable $e): void { + echo 'Error: ' . $e->getMessage() . PHP_EOL; +}); +``` + +#### reject() + +```php +$promise = React\Promise\reject(\Throwable $reason); +``` + +Creates a rejected promise for the supplied `$reason`. + +Note that the [`\Throwable`](https://www.php.net/manual/en/class.throwable.php) interface introduced in PHP 7 covers +both user land [`\Exception`](https://www.php.net/manual/en/class.exception.php)'s and +[`\Error`](https://www.php.net/manual/en/class.error.php) internal PHP errors. By enforcing `\Throwable` as reason to +reject a promise, any language error or user land exception can be used to reject a promise. + +The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface) +and can be consumed like any other promise: + +```php +$promise = React\Promise\reject(new RuntimeException('Request failed')); + +$promise->then(function (int $result): void { + var_dump($result); +}, function (\Throwable $e): void { + echo 'Error: ' . $e->getMessage() . PHP_EOL; +}); +``` + +Note that rejected promises should always be handled similar to how any +exceptions should always be caught in a `try` + `catch` block. If you remove the +last reference to a rejected promise that has not been handled, it will +report an unhandled promise rejection: + +```php +function incorrect(): int +{ + $promise = React\Promise\reject(new RuntimeException('Request failed')); + + // Commented out: No rejection handler registered here. + // $promise->then(null, function (\Throwable $e): void { /* ignore */ }); + + // Returning from a function will remove all local variable references, hence why + // this will report an unhandled promise rejection here. + return 42; +} + +// Calling this function will log an error message plus its stack trace: +// Unhandled promise rejection with RuntimeException: Request failed in example.php:10 +incorrect(); +``` + +A rejected promise will be considered "handled" if you catch the rejection +reason with either the [`then()` method](#promiseinterfacethen), the +[`catch()` method](#promiseinterfacecatch), or the +[`finally()` method](#promiseinterfacefinally). Note that each of these methods +return a new promise that may again be rejected if you re-throw an exception. + +A rejected promise will also be considered "handled" if you abort the operation +with the [`cancel()` method](#promiseinterfacecancel) (which in turn would +usually reject the promise if it is still pending). + +See also the [`set_rejection_handler()` function](#set_rejection_handler). + +#### all() + +```php +$promise = React\Promise\all(iterable $promisesOrValues); +``` + +Returns a promise that will resolve only once all the items in +`$promisesOrValues` have resolved. The resolution value of the returned promise +will be an array containing the resolution values of each of the items in +`$promisesOrValues`. + +#### race() + +```php +$promise = React\Promise\race(iterable $promisesOrValues); +``` + +Initiates a competitive race that allows one winner. Returns a promise which is +resolved in the same way the first settled promise resolves. + +The returned promise will become **infinitely pending** if `$promisesOrValues` +contains 0 items. + +#### any() + +```php +$promise = React\Promise\any(iterable $promisesOrValues); +``` + +Returns a promise that will resolve when any one of the items in +`$promisesOrValues` resolves. The resolution value of the returned promise +will be the resolution value of the triggering item. + +The returned promise will only reject if *all* items in `$promisesOrValues` are +rejected. The rejection value will be a `React\Promise\Exception\CompositeException` +which holds all rejection reasons. The rejection reasons can be obtained with +`CompositeException::getThrowables()`. + +The returned promise will also reject with a `React\Promise\Exception\LengthException` +if `$promisesOrValues` contains 0 items. + +#### set_rejection_handler() + +```php +React\Promise\set_rejection_handler(?callable $callback): ?callable; +``` + +Sets the global rejection handler for unhandled promise rejections. + +Note that rejected promises should always be handled similar to how any +exceptions should always be caught in a `try` + `catch` block. If you remove +the last reference to a rejected promise that has not been handled, it will +report an unhandled promise rejection. See also the [`reject()` function](#reject) +for more details. + +The `?callable $callback` argument MUST be a valid callback function that +accepts a single `Throwable` argument or a `null` value to restore the +default promise rejection handler. The return value of the callback function +will be ignored and has no effect, so you SHOULD return a `void` value. The +callback function MUST NOT throw or the program will be terminated with a +fatal error. + +The function returns the previous rejection handler or `null` if using the +default promise rejection handler. + +The default promise rejection handler will log an error message plus its stack +trace: + +```php +// Unhandled promise rejection with RuntimeException: Unhandled in example.php:2 +React\Promise\reject(new RuntimeException('Unhandled')); +``` + +The promise rejection handler may be used to use customize the log message or +write to custom log targets. As a rule of thumb, this function should only be +used as a last resort and promise rejections are best handled with either the +[`then()` method](#promiseinterfacethen), the +[`catch()` method](#promiseinterfacecatch), or the +[`finally()` method](#promiseinterfacefinally). +See also the [`reject()` function](#reject) for more details. + +## Examples + +### How to use Deferred + +```php +function getAwesomeResultPromise() +{ + $deferred = new React\Promise\Deferred(); + + // Execute a Node.js-style function using the callback pattern + computeAwesomeResultAsynchronously(function (\Throwable $error, $result) use ($deferred) { + if ($error) { + $deferred->reject($error); + } else { + $deferred->resolve($result); + } + }); + + // Return the promise + return $deferred->promise(); +} + +getAwesomeResultPromise() + ->then( + function ($value) { + // Deferred resolved, do something with $value + }, + function (\Throwable $reason) { + // Deferred rejected, do something with $reason + } + ); +``` + +### How promise forwarding works + +A few simple examples to show how the mechanics of Promises/A forwarding works. +These examples are contrived, of course, and in real usage, promise chains will +typically be spread across several function calls, or even several levels of +your application architecture. + +#### Resolution forwarding + +Resolved promises forward resolution values to the next promise. +The first promise, `$deferred->promise()`, will resolve with the value passed +to `$deferred->resolve()` below. + +Each call to `then()` returns a new promise that will resolve with the return +value of the previous handler. This creates a promise "pipeline". + +```php +$deferred = new React\Promise\Deferred(); + +$deferred->promise() + ->then(function ($x) { + // $x will be the value passed to $deferred->resolve() below + // and returns a *new promise* for $x + 1 + return $x + 1; + }) + ->then(function ($x) { + // $x === 2 + // This handler receives the return value of the + // previous handler. + return $x + 1; + }) + ->then(function ($x) { + // $x === 3 + // This handler receives the return value of the + // previous handler. + return $x + 1; + }) + ->then(function ($x) { + // $x === 4 + // This handler receives the return value of the + // previous handler. + echo 'Resolve ' . $x; + }); + +$deferred->resolve(1); // Prints "Resolve 4" +``` + +#### Rejection forwarding + +Rejected promises behave similarly, and also work similarly to try/catch: +When you catch an exception, you must rethrow for it to propagate. + +Similarly, when you handle a rejected promise, to propagate the rejection, +"rethrow" it by either returning a rejected promise, or actually throwing +(since promise translates thrown exceptions into rejections) + +```php +$deferred = new React\Promise\Deferred(); + +$deferred->promise() + ->then(function ($x) { + throw new \Exception($x + 1); + }) + ->catch(function (\Exception $x) { + // Propagate the rejection + throw $x; + }) + ->catch(function (\Exception $x) { + // Can also propagate by returning another rejection + return React\Promise\reject( + new \Exception($x->getMessage() + 1) + ); + }) + ->catch(function ($x) { + echo 'Reject ' . $x->getMessage(); // 3 + }); + +$deferred->resolve(1); // Prints "Reject 3" +``` + +#### Mixed resolution and rejection forwarding + +Just like try/catch, you can choose to propagate or not. Mixing resolutions and +rejections will still forward handler results in a predictable way. + +```php +$deferred = new React\Promise\Deferred(); + +$deferred->promise() + ->then(function ($x) { + return $x + 1; + }) + ->then(function ($x) { + throw new \Exception($x + 1); + }) + ->catch(function (\Exception $x) { + // Handle the rejection, and don't propagate. + // This is like catch without a rethrow + return $x->getMessage() + 1; + }) + ->then(function ($x) { + echo 'Mixed ' . $x; // 4 + }); + +$deferred->resolve(1); // Prints "Mixed 4" +``` From f5921f50736697514fe35a6dd5925b60ea6ec5db Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 16:14:53 +0400 Subject: [PATCH 06/18] ci: Cleanup --- .github/workflows/ci.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b3f223..eea15d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,7 @@ jobs: name: PHPUnit (PHP ${{ matrix.php }}) runs-on: ubuntu-24.04 strategy: + fail-fast: false matrix: php: - 8.4 @@ -23,10 +24,7 @@ jobs: coverage: xdebug ini-file: development - run: composer install - - run: vendor/bin/phpunit --coverage-text - if: ${{ matrix.php >= 7.3 }} - - run: vendor/bin/phpunit --coverage-text -c phpunit.xml.legacy - if: ${{ matrix.php < 7.3 }} + - run: composer test:cc PHPStan: name: PHPStan (PHP ${{ matrix.php }}) @@ -45,4 +43,4 @@ jobs: php-version: ${{ matrix.php }} coverage: none - run: composer install - - run: vendor/bin/phpstan + - run: composer stan From 94881935b4b3bf1022983b12f7d1d2b98eb7c5b6 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 16:25:44 +0400 Subject: [PATCH 07/18] refactor: refactor tests using rector --- composer.json | 6 ++-- rector.php | 16 +++++++++ tests/DeferredTest.php | 6 ++-- tests/FunctionAnyTest.php | 6 ++-- tests/FunctionCheckTypehintTest.php | 6 ++-- tests/FunctionRaceTest.php | 8 ++--- tests/Internal/FulfilledPromiseTest.php | 6 ++-- tests/Internal/RejectedPromiseTest.php | 6 ++-- tests/PromiseTest.php | 36 +++++++++---------- tests/PromiseTest/CancelTestTrait.php | 18 +++++----- .../PromiseTest/PromiseFulfilledTestTrait.php | 12 +++---- tests/PromiseTest/PromisePendingTestTrait.php | 4 +-- .../PromiseTest/PromiseRejectedTestTrait.php | 22 ++++++------ tests/PromiseTest/PromiseSettledTestTrait.php | 4 +-- tests/PromiseTest/RejectTestTrait.php | 4 +-- tests/PromiseTest/ResolveTestTrait.php | 4 +-- tests/types/deferred.php | 8 ++--- tests/types/promise.php | 20 +++++------ tests/types/resolve.php | 2 +- 19 files changed, 106 insertions(+), 88 deletions(-) create mode 100644 rector.php diff --git a/composer.json b/composer.json index 61ef792..051ffff 100644 --- a/composer.json +++ b/composer.json @@ -35,8 +35,9 @@ "react/promise": "^3.0" }, "require-dev": { - "phpstan/phpstan": "1.12.28 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" + "phpstan/phpstan": "1.12.28", + "phpunit/phpunit": "^9.6", + "rector/rector": "^1.2" }, "autoload": { "psr-4": { @@ -66,6 +67,7 @@ "scripts": { "stan": "phpstan", "test": "phpunit --color=always --testdox", + "refactor": "rector process --config=rector.php", "test:cc": [ "@putenv XDEBUG_MODE=coverage", "phpunit --coverage-clover=runtime/phpunit/logs/clover.xml --color=always" diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..c2b1065 --- /dev/null +++ b/rector.php @@ -0,0 +1,16 @@ +withPaths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + // uncomment to reach your current PHP version + // ->withPhpSets(php81: true) + ->withTypeCoverageLevel(0) + ->withDeadCodeLevel(0) + ->withCodeQualityLevel(0); diff --git a/tests/DeferredTest.php b/tests/DeferredTest.php index f63c0fd..1140dbe 100644 --- a/tests/DeferredTest.php +++ b/tests/DeferredTest.php @@ -30,7 +30,7 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException(): void { gc_collect_cycles(); - $deferred = new Deferred(function ($resolve, $reject) { + $deferred = new Deferred(function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $deferred->promise()->cancel(); @@ -45,7 +45,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejects gc_collect_cycles(); gc_collect_cycles(); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on - $deferred = new Deferred(function ($resolve, $reject) { + $deferred = new Deferred(function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $deferred->promise()->then()->cancel(); @@ -61,7 +61,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenc gc_collect_cycles(); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on /** @var Deferred $deferred */ - $deferred = new Deferred(function () use (&$deferred) { + $deferred = new Deferred(function () use (&$deferred): void { assert($deferred instanceof Deferred); }); diff --git a/tests/FunctionAnyTest.php b/tests/FunctionAnyTest.php index 563f882..0b95b37 100644 --- a/tests/FunctionAnyTest.php +++ b/tests/FunctionAnyTest.php @@ -205,8 +205,8 @@ public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue /** @test */ public function shouldCancelInputArrayPromises(): void { - $promise1 = new Promise(function () {}, $this->expectCallableOnce()); - $promise2 = new Promise(function () {}, $this->expectCallableOnce()); + $promise1 = new Promise(function (): void {}, $this->expectCallableOnce()); + $promise2 = new Promise(function (): void {}, $this->expectCallableOnce()); any([$promise1, $promise2])->cancel(); } @@ -217,7 +217,7 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfill $deferred = new Deferred($this->expectCallableNever()); $deferred->resolve(null); - $promise2 = new Promise(function () {}, $this->expectCallableNever()); + $promise2 = new Promise(function (): void {}, $this->expectCallableNever()); any([$deferred->promise(), $promise2])->cancel(); } diff --git a/tests/FunctionCheckTypehintTest.php b/tests/FunctionCheckTypehintTest.php index 6f7fc0f..b5b609a 100644 --- a/tests/FunctionCheckTypehintTest.php +++ b/tests/FunctionCheckTypehintTest.php @@ -10,8 +10,8 @@ class FunctionCheckTypehintTest extends TestCase /** @test */ public function shouldAcceptClosureCallbackWithTypehint(): void { - self::assertTrue(_checkTypehint(function (InvalidArgumentException $e) {}, new InvalidArgumentException())); - self::assertFalse(_checkTypehint(function (InvalidArgumentException $e) {}, new Exception())); + self::assertTrue(_checkTypehint(function (InvalidArgumentException $e): void {}, new InvalidArgumentException())); + self::assertFalse(_checkTypehint(function (InvalidArgumentException $e): void {}, new Exception())); } /** @test */ @@ -151,7 +151,7 @@ public function shouldAcceptStaticClassCallbackWithDNFTypehint(): void /** @test */ public function shouldAcceptClosureCallbackWithoutTypehint(): void { - self::assertTrue(_checkTypehint(function (InvalidArgumentException $e) { + self::assertTrue(_checkTypehint(function (InvalidArgumentException $e): void { }, new InvalidArgumentException())); } diff --git a/tests/FunctionRaceTest.php b/tests/FunctionRaceTest.php index a0ac05b..90264d0 100644 --- a/tests/FunctionRaceTest.php +++ b/tests/FunctionRaceTest.php @@ -129,8 +129,8 @@ public function shouldRejectIfFirstSettledPromiseRejects(): void /** @test */ public function shouldCancelInputArrayPromises(): void { - $promise1 = new Promise(function () {}, $this->expectCallableOnce()); - $promise2 = new Promise(function () {}, $this->expectCallableOnce()); + $promise1 = new Promise(function (): void {}, $this->expectCallableOnce()); + $promise2 = new Promise(function (): void {}, $this->expectCallableOnce()); race([$promise1, $promise2])->cancel(); } @@ -141,7 +141,7 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfill $deferred = new Deferred($this->expectCallableNever()); $deferred->resolve(null); - $promise2 = new Promise(function () {}, $this->expectCallableNever()); + $promise2 = new Promise(function (): void {}, $this->expectCallableNever()); race([$deferred->promise(), $promise2])->cancel(); } @@ -152,7 +152,7 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseRejects $deferred = new Deferred($this->expectCallableNever()); $deferred->reject(new Exception()); - $promise2 = new Promise(function () {}, $this->expectCallableNever()); + $promise2 = new Promise(function (): void {}, $this->expectCallableNever()); race([$deferred->promise(), $promise2])->cancel(); } diff --git a/tests/Internal/FulfilledPromiseTest.php b/tests/Internal/FulfilledPromiseTest.php index b216e1d..3df4eb8 100644 --- a/tests/Internal/FulfilledPromiseTest.php +++ b/tests/Internal/FulfilledPromiseTest.php @@ -33,15 +33,15 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm return $promise; }, - 'resolve' => function ($value = null) use (&$promise) { + 'resolve' => function ($value = null) use (&$promise): void { if (!$promise) { $promise = new FulfilledPromise($value); } }, - 'reject' => function () { + 'reject' => function (): void { throw new LogicException('You cannot call reject() for React\Promise\FulfilledPromise'); }, - 'settle' => function ($value = null) use (&$promise) { + 'settle' => function ($value = null) use (&$promise): void { if (!$promise) { $promise = new FulfilledPromise($value); } diff --git a/tests/Internal/RejectedPromiseTest.php b/tests/Internal/RejectedPromiseTest.php index 2338b4f..c755498 100644 --- a/tests/Internal/RejectedPromiseTest.php +++ b/tests/Internal/RejectedPromiseTest.php @@ -30,15 +30,15 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm return $promise; }, - 'resolve' => function () { + 'resolve' => function (): void { throw new LogicException('You cannot call resolve() for React\Promise\RejectedPromise'); }, - 'reject' => function (\Throwable $reason) use (&$promise) { + 'reject' => function (\Throwable $reason) use (&$promise): void { if (!$promise) { $promise = new RejectedPromise($reason); } }, - 'settle' => function ($reason = '') use (&$promise) { + 'settle' => function ($reason = '') use (&$promise): void { if (!$promise) { if (!$reason instanceof Exception) { $reason = new Exception((string) $reason); diff --git a/tests/PromiseTest.php b/tests/PromiseTest.php index d097b90..6e085f4 100644 --- a/tests/PromiseTest.php +++ b/tests/PromiseTest.php @@ -42,7 +42,7 @@ public function shouldRejectIfResolverThrowsException(): void { $exception = new Exception('foo'); - $promise = new Promise(function () use ($exception) { + $promise = new Promise(function () use ($exception): void { throw $exception; }); @@ -60,7 +60,7 @@ public function shouldRejectIfResolverThrowsException(): void public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithException(): void { gc_collect_cycles(); - $promise = new Promise(function ($resolve) { + $promise = new Promise(function ($resolve): void { $resolve(new \Exception('foo')); }); unset($promise); @@ -72,7 +72,7 @@ public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithE public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptionWithoutResolver(): void { gc_collect_cycles(); - $promise = new Promise(function () { + $promise = new Promise(function (): void { throw new \Exception('foo'); }); @@ -87,7 +87,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithException(): void { gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject) { + $promise = new Promise(function ($resolve, $reject): void { $reject(new \Exception('foo')); }); @@ -102,7 +102,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithExc public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException(): void { gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject) { }, function ($resolve, $reject) { + $promise = new Promise(function ($resolve, $reject): void { }, function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $promise->cancel(); @@ -115,7 +115,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithEx public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException(): void { gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject) { }, function ($resolve, $reject) { + $promise = new Promise(function ($resolve, $reject): void { }, function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $promise->then()->then()->then()->cancel(); @@ -128,7 +128,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejects public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsException(): void { gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject) { + $promise = new Promise(function ($resolve, $reject): void { throw new \Exception('foo'); }); @@ -143,7 +143,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise(): void { gc_collect_cycles(); - $promise = new Promise(function () { }); + $promise = new Promise(function (): void { }); unset($promise); $this->assertSame(0, gc_collect_cycles()); @@ -153,7 +153,7 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithThenFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function () { }); + $promise = new Promise(function (): void { }); $promise->then()->then()->then(); unset($promise); @@ -164,8 +164,8 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithCatchFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function () { }); - $promise->catch(function () { }); + $promise = new Promise(function (): void { }); + $promise->catch(function (): void { }); unset($promise); $this->assertSame(0, gc_collect_cycles()); @@ -175,8 +175,8 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithFinallyFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function () { }); - $promise->finally(function () { }); + $promise = new Promise(function (): void { }); + $promise->finally(function (): void { }); unset($promise); $this->assertSame(0, gc_collect_cycles()); @@ -189,8 +189,8 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithOtherwiseFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function () { }); - $promise->otherwise(function () { }); + $promise = new Promise(function (): void { }); + $promise->otherwise(function (): void { }); unset($promise); $this->assertSame(0, gc_collect_cycles()); @@ -203,8 +203,8 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithAlwaysFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function () { }); - $promise->always(function () { }); + $promise = new Promise(function (): void { }); + $promise->always(function (): void { }); unset($promise); $this->assertSame(0, gc_collect_cycles()); @@ -214,7 +214,7 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro public function shouldFulfillIfFullfilledWithSimplePromise(): void { gc_collect_cycles(); - $promise = new Promise(function () { + $promise = new Promise(function (): void { throw new Exception('foo'); }); diff --git a/tests/PromiseTest/CancelTestTrait.php b/tests/PromiseTest/CancelTestTrait.php index d119c1b..ebd8210 100644 --- a/tests/PromiseTest/CancelTestTrait.php +++ b/tests/PromiseTest/CancelTestTrait.php @@ -14,7 +14,7 @@ abstract public function getPromiseTestAdapter(?callable $canceller = null): Pro public function cancelShouldCallCancellerWithResolverArguments(): void { $args = []; - $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject) use (&$args) { + $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject) use (&$args): void { $args = func_get_args(); }); @@ -29,7 +29,7 @@ public function cancelShouldCallCancellerWithResolverArguments(): void public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed(): void { $args = null; - $adapter = $this->getPromiseTestAdapter(function () use (&$args) { + $adapter = $this->getPromiseTestAdapter(function () use (&$args): void { $args = func_num_args(); }); @@ -41,7 +41,7 @@ public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed(): void /** @test */ public function cancelShouldFulfillPromiseIfCancellerFulfills(): void { - $adapter = $this->getPromiseTestAdapter(function ($resolve) { + $adapter = $this->getPromiseTestAdapter(function ($resolve): void { $resolve(1); }); @@ -62,7 +62,7 @@ public function cancelShouldRejectPromiseIfCancellerRejects(): void { $exception = new Exception(); - $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject) use ($exception) { + $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject) use ($exception): void { $reject($exception); }); @@ -83,7 +83,7 @@ public function cancelShouldRejectPromiseWithExceptionIfCancellerThrows(): void { $e = new Exception(); - $adapter = $this->getPromiseTestAdapter(function () use ($e) { + $adapter = $this->getPromiseTestAdapter(function () use ($e): void { throw $e; }); @@ -106,7 +106,7 @@ public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves(): void $mock ->expects($this->once()) ->method('__invoke') - ->will($this->returnCallback(function ($resolve) { + ->will($this->returnCallback(function ($resolve): void { $resolve(null); })); @@ -119,7 +119,7 @@ public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves(): void /** @test */ public function cancelShouldHaveNoEffectIfCancellerDoesNothing(): void { - $adapter = $this->getPromiseTestAdapter(function () {}); + $adapter = $this->getPromiseTestAdapter(function (): void {}); $adapter->promise() ->then($this->expectCallableNever(), $this->expectCallableNever()); @@ -135,7 +135,7 @@ public function cancelShouldCallCancellerFromDeepNestedPromiseChain(): void $promise = $adapter->promise() ->then(function () { - return new Promise\Promise(function () {}); + return new Promise\Promise(function (): void {}); }) ->then(function () { $d = new Promise\Deferred(); @@ -143,7 +143,7 @@ public function cancelShouldCallCancellerFromDeepNestedPromiseChain(): void return $d->promise(); }) ->then(function () { - return new Promise\Promise(function () {}); + return new Promise\Promise(function (): void {}); }); $promise->cancel(); diff --git a/tests/PromiseTest/PromiseFulfilledTestTrait.php b/tests/PromiseTest/PromiseFulfilledTestTrait.php index 172c457..5ae4096 100644 --- a/tests/PromiseTest/PromiseFulfilledTestTrait.php +++ b/tests/PromiseTest/PromiseFulfilledTestTrait.php @@ -192,8 +192,8 @@ public function thenShouldContinueToExecuteCallbacksWhenPriorCallbackSuspendsFib $adapter = $this->getPromiseTestAdapter(); $adapter->resolve(42); - $fiber = new \Fiber(function () use ($adapter) { - $adapter->promise()->then(function (int $value) { + $fiber = new \Fiber(function () use ($adapter): void { + $adapter->promise()->then(function (int $value): void { \Fiber::suspend($value); }); }); @@ -244,7 +244,7 @@ public function finallyShouldNotSuppressValueForFulfilledPromise(): void $adapter->resolve($value); $adapter->promise() - ->finally(function () {}) + ->finally(function (): void {}) ->then($mock); } @@ -305,7 +305,7 @@ public function finallyShouldRejectWhenHandlerThrowsForFulfilledPromise(): void $adapter->resolve(1); $adapter->promise() - ->finally(function () use ($exception) { + ->finally(function () use ($exception): void { throw $exception; }) ->then(null, $mock); @@ -362,7 +362,7 @@ public function alwaysShouldNotSuppressValueForFulfilledPromise(): void $adapter->resolve($value); $adapter->promise() - ->always(function () {}) + ->always(function (): void {}) ->then($mock); } @@ -432,7 +432,7 @@ public function alwaysShouldRejectWhenHandlerThrowsForFulfilledPromise(): void $adapter->resolve(1); $adapter->promise() - ->always(function () use ($exception) { + ->always(function () use ($exception): void { throw $exception; }) ->then(null, $mock); diff --git a/tests/PromiseTest/PromisePendingTestTrait.php b/tests/PromiseTest/PromisePendingTestTrait.php index db5e2e4..f0ae13c 100644 --- a/tests/PromiseTest/PromisePendingTestTrait.php +++ b/tests/PromiseTest/PromisePendingTestTrait.php @@ -39,7 +39,7 @@ public function finallyShouldReturnAPromiseForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); - self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->finally(function () {})); + self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->finally(function (): void {})); } /** @@ -62,6 +62,6 @@ public function alwaysShouldReturnAPromiseForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); - self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->always(function () {})); + self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->always(function (): void {})); } } diff --git a/tests/PromiseTest/PromiseRejectedTestTrait.php b/tests/PromiseTest/PromiseRejectedTestTrait.php index a125698..811c9f2 100644 --- a/tests/PromiseTest/PromiseRejectedTestTrait.php +++ b/tests/PromiseTest/PromiseRejectedTestTrait.php @@ -71,7 +71,7 @@ public function shouldForwardUndefinedRejectionValue(): void $adapter->promise() ->then( $this->expectCallableNever(), - function () { + function (): void { // Presence of rejection handler is enough to switch back // to resolve mode, even though it returns undefined. // The ONLY way to propagate a rejection is to re-throw or @@ -224,7 +224,7 @@ public function catchShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExcept $adapter->reject($exception); $adapter->promise() - ->catch(function ($reason) use ($mock) { + ->catch(function ($reason) use ($mock): void { $mock($reason); }); } @@ -244,7 +244,7 @@ public function catchShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejec $adapter->reject($exception); $adapter->promise() - ->catch(function (InvalidArgumentException $reason) use ($mock) { + ->catch(function (InvalidArgumentException $reason) use ($mock): void { $mock($reason); }); } @@ -260,7 +260,7 @@ public function catchShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchTypehint $adapter->reject($exception); $adapter->promise() - ->catch(function (InvalidArgumentException $reason) use ($mock) { + ->catch(function (InvalidArgumentException $reason) use ($mock): void { $mock($reason); })->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection } @@ -280,7 +280,7 @@ public function finallyShouldNotSuppressRejectionForRejectedPromise(): void $adapter->reject($exception); $adapter->promise() - ->finally(function () {}) + ->finally(function (): void {}) ->then(null, $mock); } @@ -342,7 +342,7 @@ public function finallyShouldRejectWhenHandlerThrowsForRejectedPromise(): void $adapter->reject($exception1); $adapter->promise() - ->finally(function () use ($exception2) { + ->finally(function () use ($exception2): void { throw $exception2; }) ->then(null, $mock); @@ -418,7 +418,7 @@ public function otherwiseShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnEx $adapter->reject($exception); $adapter->promise() - ->otherwise(function ($reason) use ($mock) { + ->otherwise(function ($reason) use ($mock): void { $mock($reason); }); } @@ -441,7 +441,7 @@ public function otherwiseShouldInvokeRejectionHandlerIfReasonMatchesTypehintForR $adapter->reject($exception); $adapter->promise() - ->otherwise(function (InvalidArgumentException $reason) use ($mock) { + ->otherwise(function (InvalidArgumentException $reason) use ($mock): void { $mock($reason); }); } @@ -460,7 +460,7 @@ public function otherwiseShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchType $adapter->reject($exception); $adapter->promise() - ->otherwise(function (InvalidArgumentException $reason) use ($mock) { + ->otherwise(function (InvalidArgumentException $reason) use ($mock): void { $mock($reason); })->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection } @@ -483,7 +483,7 @@ public function alwaysShouldNotSuppressRejectionForRejectedPromise(): void $adapter->reject($exception); $adapter->promise() - ->always(function () {}) + ->always(function (): void {}) ->then(null, $mock); } @@ -554,7 +554,7 @@ public function alwaysShouldRejectWhenHandlerThrowsForRejectedPromise(): void $adapter->reject($exception1); $adapter->promise() - ->always(function () use ($exception2) { + ->always(function () use ($exception2): void { throw $exception2; }) ->then(null, $mock); diff --git a/tests/PromiseTest/PromiseSettledTestTrait.php b/tests/PromiseTest/PromiseSettledTestTrait.php index 093ab8b..0ac64ac 100644 --- a/tests/PromiseTest/PromiseSettledTestTrait.php +++ b/tests/PromiseTest/PromiseSettledTestTrait.php @@ -52,7 +52,7 @@ public function finallyShouldReturnAPromiseForSettledPromise(): void $adapter = $this->getPromiseTestAdapter(); $adapter->settle(null); - self::assertInstanceOf(PromiseInterface::class, $promise = $adapter->promise()->finally(function () {})); + self::assertInstanceOf(PromiseInterface::class, $promise = $adapter->promise()->finally(function (): void {})); if ($promise instanceof RejectedPromise) { $promise->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection @@ -68,7 +68,7 @@ public function alwaysShouldReturnAPromiseForSettledPromise(): void $adapter = $this->getPromiseTestAdapter(); $adapter->settle(null); - self::assertInstanceOf(PromiseInterface::class, $promise = $adapter->promise()->always(function () {})); + self::assertInstanceOf(PromiseInterface::class, $promise = $adapter->promise()->always(function (): void {})); if ($promise instanceof RejectedPromise) { $promise->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection diff --git a/tests/PromiseTest/RejectTestTrait.php b/tests/PromiseTest/RejectTestTrait.php index eb1d891..f6eb52a 100644 --- a/tests/PromiseTest/RejectTestTrait.php +++ b/tests/PromiseTest/RejectTestTrait.php @@ -121,7 +121,7 @@ public function finallyShouldNotSuppressRejection(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function () {}) + ->finally(function (): void {}) ->then(null, $mock); $adapter->reject($exception); @@ -185,7 +185,7 @@ public function finallyShouldRejectWhenHandlerThrowsForRejection(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function () use ($exception) { + ->finally(function () use ($exception): void { throw $exception; }) ->then(null, $mock); diff --git a/tests/PromiseTest/ResolveTestTrait.php b/tests/PromiseTest/ResolveTestTrait.php index 2a23065..0fc3941 100644 --- a/tests/PromiseTest/ResolveTestTrait.php +++ b/tests/PromiseTest/ResolveTestTrait.php @@ -181,7 +181,7 @@ public function finallyShouldNotSuppressValue(): void ->with($this->identicalTo($value)); $adapter->promise() - ->finally(function () {}) + ->finally(function (): void {}) ->then($mock); $adapter->resolve($value); @@ -245,7 +245,7 @@ public function finallyShouldRejectWhenHandlerThrowsForFulfillment(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function () use ($exception) { + ->finally(function () use ($exception): void { throw $exception; }) ->then(null, $mock); diff --git a/tests/types/deferred.php b/tests/types/deferred.php index d468849..8f92ca4 100644 --- a/tests/types/deferred.php +++ b/tests/types/deferred.php @@ -26,23 +26,23 @@ // invalid number of arguments passed to $canceller /** @phpstan-ignore-next-line */ -$deferred = new Deferred(function ($a, $b, $c) { }); +$deferred = new Deferred(function ($a, $b, $c): void { }); assertType('React\Promise\Deferred', $deferred); // invalid types for arguments of $canceller /** @phpstan-ignore-next-line */ -$deferred = new Deferred(function (int $a, string $b) { }); +$deferred = new Deferred(function (int $a, string $b): void { }); assertType('React\Promise\Deferred', $deferred); // invalid number of arguments passed to $resolve -$deferred = new Deferred(function (callable $resolve) { +$deferred = new Deferred(function (callable $resolve): void { /** @phpstan-ignore-next-line */ $resolve(); }); assertType('React\Promise\Deferred', $deferred); // invalid type passed to $reject -$deferred = new Deferred(function (callable $resolve, callable $reject) { +$deferred = new Deferred(function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(2); }); diff --git a/tests/types/promise.php b/tests/types/promise.php index fa5b15c..4a1afc8 100644 --- a/tests/types/promise.php +++ b/tests/types/promise.php @@ -29,31 +29,31 @@ // invalid number of arguments for $resolver /** @phpstan-ignore-next-line */ -$promise = new Promise(function ($a, $b, $c) { }); +$promise = new Promise(function ($a, $b, $c): void { }); assert($promise instanceof Promise); // assertType('React\Promise\PromiseInterface', $promise); // invalid types for arguments of $resolver /** @phpstan-ignore-next-line */ -$promise = new Promise(function (int $a, string $b) { }); +$promise = new Promise(function (int $a, string $b): void { }); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $resolve -$promise = new Promise(function (callable $resolve) { +$promise = new Promise(function (callable $resolve): void { /** @phpstan-ignore-next-line */ $resolve(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $reject -$promise = new Promise(function (callable $resolve, callable $reject) { +$promise = new Promise(function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid type passed to $reject -$promise = new Promise(function (callable $resolve, callable $reject) { +$promise = new Promise(function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(2); }); @@ -61,30 +61,30 @@ // invalid number of arguments for $canceller /** @phpstan-ignore-next-line */ -$promise = new Promise(function () { }, function ($a, $b, $c) { }); +$promise = new Promise(function (): void { }, function ($a, $b, $c): void { }); // assertType('React\Promise\PromiseInterface', $promise); // invalid types for arguments of $canceller /** @phpstan-ignore-next-line */ -$promise = new Promise(function () { }, function (int $a, string $b) { }); +$promise = new Promise(function (): void { }, function (int $a, string $b): void { }); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $resolve -$promise = new Promise(function () { }, function (callable $resolve) { +$promise = new Promise(function (): void { }, function (callable $resolve): void { /** @phpstan-ignore-next-line */ $resolve(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $reject -$promise = new Promise(function () { }, function (callable $resolve, callable $reject) { +$promise = new Promise(function (): void { }, function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid type passed to $reject -$promise = new Promise(function() { }, function (callable $resolve, callable $reject) { +$promise = new Promise(function(): void { }, function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(2); }); diff --git a/tests/types/resolve.php b/tests/types/resolve.php index 7206a23..33f67db 100644 --- a/tests/types/resolve.php +++ b/tests/types/resolve.php @@ -42,7 +42,7 @@ function stringOrIntPromise(): PromiseInterface { })); assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $bool): void { })); -assertType('React\Promise\PromiseInterface', resolve(false)->then(function (bool $bool): void { })->then(function (null $value) { })); +assertType('React\Promise\PromiseInterface', resolve(false)->then(function (bool $bool): void { })->then(function (null $value): void { })); $value = null; assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $v) use (&$value): void { From 3088bdd414417c05075773b7f7486f4b6de48cde Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 16:42:37 +0400 Subject: [PATCH 08/18] refactor: migrate codebase to PHP 8.1 --- src/Deferred.php | 2 +- src/Exception/CompositeException.php | 7 +-- src/Internal/CancellationQueue.php | 5 +-- src/Internal/FulfilledPromise.php | 9 ++-- src/Internal/RejectedPromise.php | 14 +++--- src/Promise.php | 19 ++++---- tests/FunctionAnyTest.php | 6 +-- tests/FunctionResolveTest.php | 12 ++--- .../PromiseAdapter/CallbackPromiseAdapter.php | 6 +-- .../PromiseAdapterInterface.php | 5 +-- tests/PromiseTest.php | 4 +- tests/PromiseTest/CancelTestTrait.php | 8 +--- .../PromiseTest/PromiseFulfilledTestTrait.php | 40 ++++++----------- .../PromiseTest/PromiseRejectedTestTrait.php | 44 +++++++------------ tests/PromiseTest/RejectTestTrait.php | 14 +++--- tests/PromiseTest/ResolveTestTrait.php | 15 +++---- tests/types/reject.php | 40 +++++------------ tests/types/resolve.php | 32 ++++---------- 18 files changed, 89 insertions(+), 193 deletions(-) diff --git a/src/Deferred.php b/src/Deferred.php index 80b8fcf..bbc6785 100644 --- a/src/Deferred.php +++ b/src/Deferred.php @@ -40,7 +40,7 @@ public function promise(): PromiseInterface /** * @param T $value */ - public function resolve($value): void + public function resolve(mixed $value): void { ($this->resolveCallback)($value); } diff --git a/src/Exception/CompositeException.php b/src/Exception/CompositeException.php index 2e672a0..9365b42 100644 --- a/src/Exception/CompositeException.php +++ b/src/Exception/CompositeException.php @@ -11,15 +11,10 @@ */ class CompositeException extends \Exception { - /** @var \Throwable[] */ - private $throwables; - /** @param \Throwable[] $throwables */ - public function __construct(array $throwables, string $message = '', int $code = 0, ?\Throwable $previous = null) + public function __construct(private readonly array $throwables, string $message = '', int $code = 0, ?\Throwable $previous = null) { parent::__construct($message, $code, $previous); - - $this->throwables = $throwables; } /** diff --git a/src/Internal/CancellationQueue.php b/src/Internal/CancellationQueue.php index 604b19c..e270d03 100644 --- a/src/Internal/CancellationQueue.php +++ b/src/Internal/CancellationQueue.php @@ -23,10 +23,7 @@ public function __invoke(): void $this->drain(); } - /** - * @param mixed $cancellable - */ - public function enqueue($cancellable): void + public function enqueue(mixed $cancellable): void { if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) { return; diff --git a/src/Internal/FulfilledPromise.php b/src/Internal/FulfilledPromise.php index 8a66cff..7cbe8ae 100644 --- a/src/Internal/FulfilledPromise.php +++ b/src/Internal/FulfilledPromise.php @@ -20,7 +20,7 @@ final class FulfilledPromise implements PromiseInterface * @param T $value * @throws \InvalidArgumentException */ - public function __construct($value = null) + public function __construct(mixed $value = null) { if ($value instanceof PromiseInterface) { throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.'); @@ -58,12 +58,9 @@ public function catch(callable $onRejected): PromiseInterface public function finally(callable $onFulfilledOrRejected): PromiseInterface { - return $this->then(function ($value) use ($onFulfilledOrRejected): PromiseInterface { + return $this->then(fn($value): PromiseInterface => /** @var T $value */ - return resolve($onFulfilledOrRejected())->then(function () use ($value) { - return $value; - }); - }); + resolve($onFulfilledOrRejected())->then(static fn() => $value)); } public function cancel(): void diff --git a/src/Internal/RejectedPromise.php b/src/Internal/RejectedPromise.php index d8a922b..0116ccb 100644 --- a/src/Internal/RejectedPromise.php +++ b/src/Internal/RejectedPromise.php @@ -14,13 +14,11 @@ */ final class RejectedPromise implements PromiseInterface { - private \Throwable $reason; private bool $handled = false; private static ?\Closure $rejectionHandler = null; - public function __construct(\Throwable $reason) + public function __construct(private readonly \Throwable $reason) { - $this->reason = $reason; } public static function setRejectionHandler(?callable $handler): void @@ -87,11 +85,11 @@ public function catch(callable $onRejected): PromiseInterface public function finally(callable $onFulfilledOrRejected): PromiseInterface { - return $this->then(null, function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($reason): PromiseInterface { - return new RejectedPromise($reason); - }); - }); + return $this->then( + null, + fn(\Throwable $reason): PromiseInterface => resolve($onFulfilledOrRejected()) + ->then(static fn(): PromiseInterface => new RejectedPromise($reason)), + ); } public function cancel(): void diff --git a/src/Promise.php b/src/Promise.php index 0828674..2fb71c6 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -96,16 +96,13 @@ public function catch(callable $onRejected): PromiseInterface public function finally(callable $onFulfilledOrRejected): PromiseInterface { - return $this->then(static function ($value) use ($onFulfilledOrRejected): PromiseInterface { - /** @var T $value */ - return resolve($onFulfilledOrRejected())->then(function () use ($value) { - return $value; - }); - }, static function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($reason): RejectedPromise { - return new RejectedPromise($reason); - }); - }); + return $this + ->then(static fn($value): PromiseInterface => + /** @var T $value */ + resolve($onFulfilledOrRejected())->then(fn() => $value), + static fn(\Throwable $reason): PromiseInterface => resolve($onFulfilledOrRejected()) + ->then(fn(): RejectedPromise => new RejectedPromise($reason)) + ); } public function cancel(): void @@ -135,7 +132,7 @@ public function cancel(): void $root->requiredCancelRequests--; if ($root->requiredCancelRequests <= 0) { - $parentCanceller = [$root, 'cancel']; + $parentCanceller = $root->cancel(...); } } diff --git a/tests/FunctionAnyTest.php b/tests/FunctionAnyTest.php index 0b95b37..46b6c9a 100644 --- a/tests/FunctionAnyTest.php +++ b/tests/FunctionAnyTest.php @@ -16,10 +16,8 @@ public function shouldRejectWithLengthExceptionWithEmptyInputArray(): void ->expects(self::once()) ->method('__invoke') ->with( - self::callback(function ($exception) { - return $exception instanceof LengthException && - 'Must contain at least 1 item but contains only 0 items.' === $exception->getMessage(); - }) + self::callback(fn($exception) => $exception instanceof LengthException && + 'Must contain at least 1 item but contains only 0 items.' === $exception->getMessage()) ); any([]) diff --git a/tests/FunctionResolveTest.php b/tests/FunctionResolveTest.php index 1eacd34..665948b 100644 --- a/tests/FunctionResolveTest.php +++ b/tests/FunctionResolveTest.php @@ -105,14 +105,10 @@ public function shouldSupportDeepNestingInPromiseChains(): void $d = new Deferred(); $d->resolve($val); - $identity = function ($val) { - return $val; - }; + $identity = fn($val) => $val; return resolve($d->promise()->then($identity))->then( - function ($val) { - return !$val; - } + fn($val) => !$val ); }))); @@ -140,9 +136,7 @@ public function shouldSupportVeryDeepNestedPromises(): void $last = $p; for ($j = 0; $j < 150; $j++) { - $last = $last->then(function ($result) { - return $result; - }); + $last = $last->then(fn($result) => $result); } } diff --git a/tests/PromiseAdapter/CallbackPromiseAdapter.php b/tests/PromiseAdapter/CallbackPromiseAdapter.php index 9b72204..225814a 100644 --- a/tests/PromiseAdapter/CallbackPromiseAdapter.php +++ b/tests/PromiseAdapter/CallbackPromiseAdapter.php @@ -10,15 +10,11 @@ */ class CallbackPromiseAdapter implements PromiseAdapterInterface { - /** @var callable[] */ - private $callbacks; - /** * @param callable[] $callbacks */ - public function __construct(array $callbacks) + public function __construct(private array $callbacks) { - $this->callbacks = $callbacks; } /** diff --git a/tests/PromiseAdapter/PromiseAdapterInterface.php b/tests/PromiseAdapter/PromiseAdapterInterface.php index 171d03e..1699538 100644 --- a/tests/PromiseAdapter/PromiseAdapterInterface.php +++ b/tests/PromiseAdapter/PromiseAdapterInterface.php @@ -14,10 +14,7 @@ interface PromiseAdapterInterface */ public function promise(): PromiseInterface; - /** - * @param mixed $value - */ - public function resolve($value): void; + public function resolve(mixed $value): void; public function reject(): void; public function settle(): void; } diff --git a/tests/PromiseTest.php b/tests/PromiseTest.php index 6e085f4..d459b40 100644 --- a/tests/PromiseTest.php +++ b/tests/PromiseTest.php @@ -28,9 +28,7 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm assert(is_callable($rejectCallback)); return new CallbackPromiseAdapter([ - 'promise' => function () use ($promise) { - return $promise; - }, + 'promise' => fn() => $promise, 'resolve' => $resolveCallback, 'reject' => $rejectCallback, 'settle' => $resolveCallback, diff --git a/tests/PromiseTest/CancelTestTrait.php b/tests/PromiseTest/CancelTestTrait.php index ebd8210..6e77e85 100644 --- a/tests/PromiseTest/CancelTestTrait.php +++ b/tests/PromiseTest/CancelTestTrait.php @@ -134,17 +134,13 @@ public function cancelShouldCallCancellerFromDeepNestedPromiseChain(): void $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); $promise = $adapter->promise() - ->then(function () { - return new Promise\Promise(function (): void {}); - }) + ->then(fn() => new Promise\Promise(function (): void {})) ->then(function () { $d = new Promise\Deferred(); return $d->promise(); }) - ->then(function () { - return new Promise\Promise(function (): void {}); - }); + ->then(fn() => new Promise\Promise(function (): void {})); $promise->cancel(); } diff --git a/tests/PromiseTest/PromiseFulfilledTestTrait.php b/tests/PromiseTest/PromiseFulfilledTestTrait.php index 5ae4096..c128b6d 100644 --- a/tests/PromiseTest/PromiseFulfilledTestTrait.php +++ b/tests/PromiseTest/PromiseFulfilledTestTrait.php @@ -88,9 +88,7 @@ public function thenShouldForwardCallbackResultToNextCallback(): void $adapter->resolve(1); $adapter->promise() ->then( - function ($val) { - return $val + 1; - }, + fn($val) => $val + 1, $this->expectCallableNever() ) ->then( @@ -113,9 +111,7 @@ public function thenShouldForwardPromisedCallbackResultValueToNextCallback(): vo $adapter->resolve(1); $adapter->promise() ->then( - function ($val) { - return resolve($val + 1); - }, + fn($val) => resolve($val + 1), $this->expectCallableNever() ) ->then( @@ -140,9 +136,7 @@ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackReturnsARejec $adapter->resolve(1); $adapter->promise() ->then( - function () use ($exception) { - return reject($exception); - }, + fn() => reject($exception), $this->expectCallableNever() ) ->then( @@ -263,9 +257,8 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFul $adapter->resolve($value); $adapter->promise() - ->finally(function (): int { // @phpstan-ignore-line - return 1; - }) + // @phpstan-ignore-line + ->finally(fn(): int => 1) ->then($mock); } @@ -284,9 +277,8 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfil $adapter->resolve($value); $adapter->promise() - ->finally(function (): PromiseInterface { // @phpstan-ignore-line - return resolve(1); - }) + // @phpstan-ignore-line + ->finally(fn(): PromiseInterface => resolve(1)) ->then($mock); } @@ -326,9 +318,7 @@ public function finallyShouldRejectWhenHandlerRejectsForFulfilledPromise(): void $adapter->resolve(1); $adapter->promise() - ->finally(function () use ($exception) { - return reject($exception); - }) + ->finally(fn() => reject($exception)) ->then(null, $mock); } @@ -384,9 +374,8 @@ public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulf $adapter->resolve($value); $adapter->promise() - ->always(function (): int { // @phpstan-ignore-line - return 1; - }) + // @phpstan-ignore-line + ->always(fn(): int => 1) ->then($mock); } @@ -408,9 +397,8 @@ public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfill $adapter->resolve($value); $adapter->promise() - ->always(function (): PromiseInterface { // @phpstan-ignore-line - return resolve(1); - }) + // @phpstan-ignore-line + ->always(fn(): PromiseInterface => resolve(1)) ->then($mock); } @@ -456,9 +444,7 @@ public function alwaysShouldRejectWhenHandlerRejectsForFulfilledPromise(): void $adapter->resolve(1); $adapter->promise() - ->always(function () use ($exception) { - return reject($exception); - }) + ->always(fn() => reject($exception)) ->then(null, $mock); } } diff --git a/tests/PromiseTest/PromiseRejectedTestTrait.php b/tests/PromiseTest/PromiseRejectedTestTrait.php index 811c9f2..b12da46 100644 --- a/tests/PromiseTest/PromiseRejectedTestTrait.php +++ b/tests/PromiseTest/PromiseRejectedTestTrait.php @@ -99,9 +99,7 @@ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackDoesNotExplicitlyP $adapter->promise() ->then( $this->expectCallableNever(), - function () { - return 2; - } + fn() => 2 ) ->then( $mock, @@ -124,9 +122,7 @@ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackReturnsAResolution $adapter->promise() ->then( $this->expectCallableNever(), - function () { - return resolve(2); - } + fn() => resolve(2) ) ->then( $mock, @@ -182,9 +178,7 @@ public function shouldPropagateRejectionsWhenErrbackReturnsARejection(): void $adapter->promise() ->then( $this->expectCallableNever(), - function () use ($exception) { - return reject($exception); - } + fn() => reject($exception) ) ->then( $this->expectCallableNever(), @@ -299,9 +293,9 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseFo $adapter->reject($exception); $adapter->promise() - ->finally(function (): int { // @phpstan-ignore-line - return 1; - }) + ->finally(fn(): int => + // @phpstan-ignore-line + 1) ->then(null, $mock); } @@ -320,9 +314,9 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRe $adapter->reject($exception); $adapter->promise() - ->finally(function (): PromiseInterface { // @phpstan-ignore-line - return resolve(1); - }) + ->finally(fn(): PromiseInterface => + // @phpstan-ignore-line + resolve(1)) ->then(null, $mock); } @@ -364,9 +358,7 @@ public function finallyShouldRejectWhenHandlerRejectsForRejectedPromise(): void $adapter->reject($exception1); $adapter->promise() - ->finally(function () use ($exception2) { - return reject($exception2); - }) + ->finally(fn() => reject($exception2)) ->then(null, $mock); } @@ -505,9 +497,9 @@ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseFor $adapter->reject($exception); $adapter->promise() - ->finally(function (): int { // @phpstan-ignore-line - return 1; - }) + ->finally(fn(): int => + // @phpstan-ignore-line + 1) ->then(null, $mock); } @@ -529,9 +521,9 @@ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRej $adapter->reject($exception); $adapter->promise() - ->always(function (): PromiseInterface { // @phpstan-ignore-line - return resolve(1); - }) + ->always(fn(): PromiseInterface => + // @phpstan-ignore-line + resolve(1)) ->then(null, $mock); } @@ -579,9 +571,7 @@ public function alwaysShouldRejectWhenHandlerRejectsForRejectedPromise(): void $adapter->reject($exception1); $adapter->promise() - ->always(function () use ($exception2) { - return reject($exception2); - }) + ->always(fn() => reject($exception2)) ->then(null, $mock); } } diff --git a/tests/PromiseTest/RejectTestTrait.php b/tests/PromiseTest/RejectTestTrait.php index f6eb52a..6cd3854 100644 --- a/tests/PromiseTest/RejectTestTrait.php +++ b/tests/PromiseTest/RejectTestTrait.php @@ -141,9 +141,8 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromise() ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function (): int { // @phpstan-ignore-line - return 1; - }) + // @phpstan-ignore-line + ->finally(fn(): int => 1) ->then(null, $mock); $adapter->reject($exception); @@ -163,9 +162,8 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromise(): v ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function (): PromiseInterface { // @phpstan-ignore-line - return resolve(1); - }) + // @phpstan-ignore-line + ->finally(fn(): PromiseInterface => resolve(1)) ->then(null, $mock); $adapter->reject($exception); @@ -207,9 +205,7 @@ public function finallyShouldRejectWhenHandlerRejectsForRejection(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function () use ($exception) { - return reject($exception); - }) + ->finally(fn() => reject($exception)) ->then(null, $mock); $adapter->reject($exception); diff --git a/tests/PromiseTest/ResolveTestTrait.php b/tests/PromiseTest/ResolveTestTrait.php index 0fc3941..f2f6af1 100644 --- a/tests/PromiseTest/ResolveTestTrait.php +++ b/tests/PromiseTest/ResolveTestTrait.php @@ -201,9 +201,8 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromise(): vo ->with($this->identicalTo($value)); $adapter->promise() - ->finally(function (): int { // @phpstan-ignore-line - return 1; - }) + // @phpstan-ignore-line + ->finally(fn(): int => 1) ->then($mock); $adapter->resolve($value); @@ -223,9 +222,9 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromise(): void ->with($this->identicalTo($value)); $adapter->promise() - ->finally(function (): PromiseInterface { // @phpstan-ignore-line - return resolve(1); - }) + // @phpstan-ignore-line + ->finally(fn(): PromiseInterface => + resolve(1)) ->then($mock); $adapter->resolve($value); @@ -267,9 +266,7 @@ public function finallyShouldRejectWhenHandlerRejectsForFulfillment(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function () use ($exception) { - return reject($exception); - }) + ->finally(fn() => reject($exception)) ->then(null, $mock); $adapter->resolve(1); diff --git a/tests/types/reject.php b/tests/types/reject.php index fd8802e..42c34ed 100644 --- a/tests/types/reject.php +++ b/tests/types/reject.php @@ -10,50 +10,30 @@ // assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(function (): int { // return 42; // })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, function (): int { - return 42; -})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, function (): PromiseInterface { - return resolve(42); -})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, fn(): PromiseInterface => resolve(42))); // assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(function (): bool { // return true; // }, function (): int { // return 42; // })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(function (): int { - return 42; -})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(function (\UnexpectedValueException $e): int { - return 42; -})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(function (): PromiseInterface { - return resolve(42); -})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(fn(\UnexpectedValueException $e): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(fn(): PromiseInterface => resolve(42))); assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(function (): void { })); assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(function (): never { throw new \UnexpectedValueException(); })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(function (): PromiseInterface { - return reject(new \UnexpectedValueException()); -})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(fn(): PromiseInterface => reject(new \UnexpectedValueException()))); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(function (): int { - return 42; -})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(function (\UnexpectedValueException $e): int { - return 42; -})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(function (): PromiseInterface { - return resolve(42); -})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(fn(\UnexpectedValueException $e): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(fn(): PromiseInterface => resolve(42))); assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(function (): void { })); assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(function (): never { throw new \UnexpectedValueException(); })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(function (): PromiseInterface { - return reject(new \UnexpectedValueException()); -})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(fn(): PromiseInterface => reject(new \UnexpectedValueException()))); diff --git a/tests/types/resolve.php b/tests/types/resolve.php index 33f67db..d034acc 100644 --- a/tests/types/resolve.php +++ b/tests/types/resolve.php @@ -25,21 +25,13 @@ function stringOrIntPromise(): PromiseInterface { assertType('React\Promise\PromiseInterface', resolve(resolve(true))); assertType('React\Promise\PromiseInterface', resolve(true)->then(null, null)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $bool): bool { - return $bool; -})); -assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $value): int { - return 42; -})); -assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $value): PromiseInterface { - return resolve(42); -})); +assertType('React\Promise\PromiseInterface', resolve(true)->then(fn(bool $bool): bool => $bool)); +assertType('React\Promise\PromiseInterface', resolve(true)->then(fn(bool $value): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->then(fn(bool $value): PromiseInterface => resolve(42))); assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $value): never { throw new \RuntimeException(); })); -assertType('React\Promise\PromiseInterface', resolve(true)->then(null, function (\Throwable $e): int { - return 42; -})); +assertType('React\Promise\PromiseInterface', resolve(true)->then(null, fn(\Throwable $e): int => 42)); assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $bool): void { })); assertType('React\Promise\PromiseInterface', resolve(false)->then(function (bool $bool): void { })->then(function (null $value): void { })); @@ -53,12 +45,8 @@ function stringOrIntPromise(): PromiseInterface { assertType('React\Promise\PromiseInterface', resolve(true)->catch(function (\Throwable $e): never { throw $e; })); -assertType('React\Promise\PromiseInterface', resolve(true)->catch(function (\Throwable $e): int { - return 42; -})); -assertType('React\Promise\PromiseInterface', resolve(true)->catch(function (\Throwable $e): PromiseInterface { - return resolve(42); -})); +assertType('React\Promise\PromiseInterface', resolve(true)->catch(fn(\Throwable $e): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->catch(fn(\Throwable $e): PromiseInterface => resolve(42))); assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): void { })); // assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): never { @@ -71,12 +59,8 @@ function stringOrIntPromise(): PromiseInterface { assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(function (\Throwable $e): never { throw $e; })); -assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(function (\Throwable $e): int { - return 42; -})); -assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(function (\Throwable $e): PromiseInterface { - return resolve(42); -})); +assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(fn(\Throwable $e): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(fn(\Throwable $e): PromiseInterface => resolve(42))); assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): void { })); // assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): never { From edf5e2d32906cfd5d63be524b03199e68b2ae07f Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 16:46:48 +0400 Subject: [PATCH 09/18] style: install and apply Spiral Code Style --- .github/workflows/cs-fix.yml | 12 ++ .php-cs-fixer.dist.php | 13 ++ composer.json | 4 +- src/Exception/CompositeException.php | 4 +- src/Exception/LengthException.php | 4 +- src/Internal/CancellationQueue.php | 22 +-- src/Internal/FulfilledPromise.php | 7 +- src/Internal/RejectedPromise.php | 47 +++-- src/Promise.php | 31 +-- src/PromiseInterface.php | 2 - src/functions.php | 15 +- src/functions_include.php | 2 +- tests/DeferredTest.php | 12 +- tests/Fiber.php | 8 +- tests/FunctionAllTest.php | 42 ++-- tests/FunctionAnyTest.php | 71 ++++--- tests/FunctionCheckTypehintTest.php | 94 +++++---- tests/FunctionRaceTest.php | 56 ++++-- tests/FunctionRejectTest.php | 8 +- tests/FunctionResolveTest.php | 41 ++-- tests/Internal/CancellationQueueTest.php | 25 ++- tests/Internal/FulfilledPromiseTest.php | 12 +- tests/Internal/RejectedPromiseTest.php | 14 +- .../PromiseAdapter/CallbackPromiseAdapter.php | 4 +- .../PromiseAdapterInterface.php | 2 + tests/PromiseTest.php | 77 +++++--- tests/PromiseTest/CancelTestTrait.php | 73 +++++-- tests/PromiseTest/FullTestTrait.php | 14 +- .../PromiseTest/PromiseFulfilledTestTrait.php | 105 ++++++---- tests/PromiseTest/PromisePendingTestTrait.php | 16 +- .../PromiseTest/PromiseRejectedTestTrait.php | 181 +++++++++++------- tests/PromiseTest/PromiseSettledTestTrait.php | 16 +- tests/PromiseTest/RejectTestTrait.php | 68 ++++--- tests/PromiseTest/ResolveTestTrait.php | 71 ++++--- tests/TestCase.php | 5 +- .../CallbackWithIntersectionTypehintClass.php | 19 +- tests/fixtures/CallbackWithTypehintClass.php | 14 +- .../CallbackWithUnionTypehintClass.php | 19 +- .../fixtures/CallbackWithoutTypehintClass.php | 12 +- tests/fixtures/CountableException.php | 6 +- tests/types/deferred.php | 5 +- tests/types/promise.php | 15 +- tests/types/reject.php | 5 +- tests/types/resolve.php | 15 +- 44 files changed, 782 insertions(+), 506 deletions(-) create mode 100644 .github/workflows/cs-fix.yml create mode 100644 .php-cs-fixer.dist.php diff --git a/.github/workflows/cs-fix.yml b/.github/workflows/cs-fix.yml new file mode 100644 index 0000000..0395b27 --- /dev/null +++ b/.github/workflows/cs-fix.yml @@ -0,0 +1,12 @@ +on: + push: + branches: + - '*' + +name: Fix Code Style + +jobs: + cs-fix: + permissions: + contents: write + uses: spiral/gh-actions/.github/workflows/cs-fix.yml@master diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..78b194f --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,13 @@ +include(__DIR__ . '/src') + ->include(__DIR__ . '/tests') + ->include(__DIR__ . '/rector.php') + ->include(__FILE__) + ->allowRisky(false) + ->build(); diff --git a/composer.json b/composer.json index 051ffff..a65b91b 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,8 @@ "require-dev": { "phpstan/phpstan": "1.12.28", "phpunit/phpunit": "^9.6", - "rector/rector": "^1.2" + "rector/rector": "^1.2", + "spiral/code-style": "^2.2" }, "autoload": { "psr-4": { @@ -65,6 +66,7 @@ "sort-packages": true }, "scripts": { + "cs:fix": "php-cs-fixer fix -v", "stan": "phpstan", "test": "phpunit --color=always --testdox", "refactor": "rector process --config=rector.php", diff --git a/src/Exception/CompositeException.php b/src/Exception/CompositeException.php index 9365b42..716d06f 100644 --- a/src/Exception/CompositeException.php +++ b/src/Exception/CompositeException.php @@ -11,7 +11,9 @@ */ class CompositeException extends \Exception { - /** @param \Throwable[] $throwables */ + /** + * @param \Throwable[] $throwables + */ public function __construct(private readonly array $throwables, string $message = '', int $code = 0, ?\Throwable $previous = null) { parent::__construct($message, $code, $previous); diff --git a/src/Exception/LengthException.php b/src/Exception/LengthException.php index 775c48d..363d572 100644 --- a/src/Exception/LengthException.php +++ b/src/Exception/LengthException.php @@ -2,6 +2,4 @@ namespace React\Promise\Exception; -class LengthException extends \LengthException -{ -} +class LengthException extends \LengthException {} diff --git a/src/Internal/CancellationQueue.php b/src/Internal/CancellationQueue.php index e270d03..f841c66 100644 --- a/src/Internal/CancellationQueue.php +++ b/src/Internal/CancellationQueue.php @@ -13,16 +13,6 @@ final class CancellationQueue /** @var object[] */ private $queue = []; - public function __invoke(): void - { - if ($this->started) { - return; - } - - $this->started = true; - $this->drain(); - } - public function enqueue(mixed $cancellable): void { if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) { @@ -31,11 +21,21 @@ public function enqueue(mixed $cancellable): void $length = \array_push($this->queue, $cancellable); - if ($this->started && 1 === $length) { + if ($this->started && $length === 1) { $this->drain(); } } + public function __invoke(): void + { + if ($this->started) { + return; + } + + $this->started = true; + $this->drain(); + } + private function drain(): void { for ($i = \key($this->queue); isset($this->queue[$i]); $i++) { diff --git a/src/Internal/FulfilledPromise.php b/src/Internal/FulfilledPromise.php index 7cbe8ae..8e72f38 100644 --- a/src/Internal/FulfilledPromise.php +++ b/src/Internal/FulfilledPromise.php @@ -3,6 +3,7 @@ namespace React\Promise\Internal; use React\Promise\PromiseInterface; + use function React\Promise\resolve; /** @@ -36,7 +37,7 @@ public function __construct(mixed $value = null) */ public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface { - if (null === $onFulfilled) { + if ($onFulfilled === null) { return $this; } @@ -63,9 +64,7 @@ public function finally(callable $onFulfilledOrRejected): PromiseInterface resolve($onFulfilledOrRejected())->then(static fn() => $value)); } - public function cancel(): void - { - } + public function cancel(): void {} /** * @deprecated 3.0.0 Use `catch()` instead diff --git a/src/Internal/RejectedPromise.php b/src/Internal/RejectedPromise.php index 0116ccb..d2e822e 100644 --- a/src/Internal/RejectedPromise.php +++ b/src/Internal/RejectedPromise.php @@ -3,9 +3,9 @@ namespace React\Promise\Internal; use React\Promise\PromiseInterface; + use function React\Promise\_checkTypehint; use function React\Promise\resolve; -use function React\Promise\set_rejection_handler; /** * @internal @@ -17,42 +17,21 @@ final class RejectedPromise implements PromiseInterface private bool $handled = false; private static ?\Closure $rejectionHandler = null; - public function __construct(private readonly \Throwable $reason) - { - } + public function __construct(private readonly \Throwable $reason) {} public static function setRejectionHandler(?callable $handler): void { self::$rejectionHandler = $handler === null ? null : $handler(...); } - /** @throws void */ - public function __destruct() - { - if ($this->handled || self::$rejectionHandler === null) { - return; - } - - try { - (self::$rejectionHandler)($this->reason); - } catch (\Throwable $e) { - \preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match); - \assert(isset($match[1], $match[2])); - $message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2]; - - \error_log($message); - } - } - /** * @template TRejected - * @param ?callable $onFulfilled * @param ?(callable(\Throwable): (PromiseInterface|TRejected)) $onRejected * @return PromiseInterface<($onRejected is null ? never : TRejected)> */ public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface { - if (null === $onRejected) { + if ($onRejected === null) { return $this; } @@ -114,4 +93,24 @@ public function always(callable $onFulfilledOrRejected): PromiseInterface { return $this->finally($onFulfilledOrRejected); } + + /** + * @throws void + */ + public function __destruct() + { + if ($this->handled || self::$rejectionHandler === null) { + return; + } + + try { + (self::$rejectionHandler)($this->reason); + } catch (\Throwable $e) { + \preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match); + \assert(isset($match[1], $match[2])); + $message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2]; + + \error_log($message); + } + } } diff --git a/src/Promise.php b/src/Promise.php index 2fb71c6..1e852bd 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -43,12 +43,12 @@ public function __construct(callable $resolver, ?callable $canceller = null) public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface { - if (null !== $this->result) { + if ($this->result !== null) { return $this->result->then($onFulfilled, $onRejected); } - if (null === $this->canceller) { - return new static($this->resolver($onFulfilled, $onRejected)); + if ($this->canceller === null) { + return new self($this->resolver($onFulfilled, $onRejected)); } // This promise has a canceller, so we create a new child promise which @@ -59,7 +59,7 @@ public function then(?callable $onFulfilled = null, ?callable $onRejected = null $parent = $this; ++$parent->requiredCancelRequests; - return new static( + return new self( $this->resolver($onFulfilled, $onRejected), static function () use (&$parent): void { assert($parent instanceof self); @@ -70,7 +70,7 @@ static function () use (&$parent): void { } $parent = null; - } + }, ); } @@ -97,11 +97,12 @@ public function catch(callable $onRejected): PromiseInterface public function finally(callable $onFulfilledOrRejected): PromiseInterface { return $this - ->then(static fn($value): PromiseInterface => + ->then( + static fn($value): PromiseInterface => /** @var T $value */ resolve($onFulfilledOrRejected())->then(fn() => $value), static fn(\Throwable $reason): PromiseInterface => resolve($onFulfilledOrRejected()) - ->then(fn(): RejectedPromise => new RejectedPromise($reason)) + ->then(fn(): RejectedPromise => new RejectedPromise($reason)), ); } @@ -113,7 +114,7 @@ public function cancel(): void $parentCanceller = null; - if (null !== $this->result) { + if ($this->result !== null) { // Forward cancellation to rejected promise to avoid reporting unhandled rejection if ($this->result instanceof RejectedPromise) { $this->result->cancel(); @@ -125,7 +126,7 @@ public function cancel(): void // Return if the root promise is already resolved or a // FulfilledPromise or RejectedPromise - if (!$root instanceof self || null !== $root->result) { + if (!$root instanceof self || $root->result !== null) { return; } @@ -136,7 +137,7 @@ public function cancel(): void } } - if (null !== $canceller) { + if ($canceller !== null) { $this->call($canceller); } @@ -183,7 +184,7 @@ private function resolver(?callable $onFulfilled = null, ?callable $onRejected = private function reject(\Throwable $reason): void { - if (null !== $this->result) { + if ($this->result !== null) { return; } @@ -199,7 +200,7 @@ private function settle(PromiseInterface $result): void if ($result === $this) { $result = new RejectedPromise( - new \LogicException('Cannot resolve a promise with itself.') + new \LogicException('Cannot resolve a promise with itself.'), ); } @@ -231,7 +232,7 @@ private function settle(PromiseInterface $result): void */ private function unwrap(PromiseInterface $promise): PromiseInterface { - while ($promise instanceof self && null !== $promise->result) { + while ($promise instanceof self && $promise->result !== null) { /** @var PromiseInterface $promise */ $promise = $promise->result; } @@ -276,7 +277,7 @@ private function call(callable $cb): void // garbage cycles if any callback creates an Exception. // These assumptions are covered by the test suite, so if you ever feel like // refactoring this, go ahead, any alternative suggestions are welcome! - $target =& $this; + $target = & $this; $callback( static function ($value) use (&$target): void { @@ -290,7 +291,7 @@ static function (\Throwable $reason) use (&$target): void { $target->reject($reason); $target = null; } - } + }, ); } } catch (\Throwable $e) { diff --git a/src/PromiseInterface.php b/src/PromiseInterface.php index 34f3669..b533076 100644 --- a/src/PromiseInterface.php +++ b/src/PromiseInterface.php @@ -110,8 +110,6 @@ public function finally(callable $onFulfilledOrRejected): PromiseInterface; * * Once a promise is settled (either fulfilled or rejected), calling `cancel()` on * a promise has no effect. - * - * @return void */ public function cancel(): void; diff --git a/src/functions.php b/src/functions.php index 32d998f..9f5a7ec 100644 --- a/src/functions.php +++ b/src/functions.php @@ -94,14 +94,14 @@ function all(iterable $promisesOrValues): PromiseInterface function ($value) use ($i, &$values, &$toResolve, &$continue, $resolve): void { $values[$i] = $value; - if (0 === --$toResolve && !$continue) { + if (--$toResolve === 0 && !$continue) { $resolve($values); } }, function (\Throwable $reason) use (&$continue, $reject): void { $continue = false; $reject($reason); - } + }, ); if (!$continue && !\is_array($promisesOrValues)) { @@ -186,13 +186,13 @@ function ($value) use ($resolve, &$continue): void { function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continue): void { $reasons[$i] = $reason; - if (0 === --$toReject && !$continue) { + if (--$toReject === 0 && !$continue) { $reject(new CompositeException( $reasons, - 'All promises rejected.' + 'All promises rejected.', )); } - } + }, ); if (!$continue && !\is_array($promisesOrValues)) { @@ -203,12 +203,12 @@ function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continu $continue = false; if ($toReject === 0 && !$reasons) { $reject(new Exception\LengthException( - 'Must contain at least 1 item but contains only 0 items.' + 'Must contain at least 1 item but contains only 0 items.', )); } elseif ($toReject === 0) { $reject(new CompositeException( $reasons, - 'All promises rejected.' + 'All promises rejected.', )); } }, $cancellationQueue); @@ -300,6 +300,7 @@ function _checkTypehint(callable $callback, \Throwable $reason): bool break; case $type instanceof \ReflectionIntersectionType: $isTypeUnion = false; + // no break case $type instanceof \ReflectionUnionType: $types = $type->getTypes(); break; diff --git a/src/functions_include.php b/src/functions_include.php index bd0c54f..750fe6a 100644 --- a/src/functions_include.php +++ b/src/functions_include.php @@ -1,5 +1,5 @@ assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException(): void { gc_collect_cycles(); @@ -54,7 +58,9 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejects $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenceAndExplicitlyRejectWithException(): void { gc_collect_cycles(); diff --git a/tests/Fiber.php b/tests/Fiber.php index a1b196c..cca384d 100644 --- a/tests/Fiber.php +++ b/tests/Fiber.php @@ -9,14 +9,14 @@ */ class Fiber { - public static function suspend(mixed $value): void + public function __construct(callable $callback) { - // NOOP + assert(is_callable($callback)); } - public function __construct(callable $callback) + public static function suspend(mixed $value): void { - assert(is_callable($callback)); + // NOOP } public function start(): int diff --git a/tests/FunctionAllTest.php b/tests/FunctionAllTest.php index 10cfa2f..7f93714 100644 --- a/tests/FunctionAllTest.php +++ b/tests/FunctionAllTest.php @@ -2,11 +2,11 @@ namespace React\Promise; -use Exception; - class FunctionAllTest extends TestCase { - /** @test */ + /** + * @test + */ public function shouldResolveEmptyInput(): void { $mock = $this->createCallableMock(); @@ -19,7 +19,9 @@ public function shouldResolveEmptyInput(): void ->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveValuesArray(): void { $mock = $this->createCallableMock(); @@ -32,7 +34,9 @@ public function shouldResolveValuesArray(): void ->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolvePromisesArray(): void { $mock = $this->createCallableMock(); @@ -45,7 +49,9 @@ public function shouldResolvePromisesArray(): void ->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveSparseArrayInput(): void { $mock = $this->createCallableMock(); @@ -58,7 +64,9 @@ public function shouldResolveSparseArrayInput(): void ->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveValuesGenerator(): void { $mock = $this->createCallableMock(); @@ -76,7 +84,9 @@ public function shouldResolveValuesGenerator(): void all($gen)->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveValuesGeneratorEmpty(): void { $mock = $this->createCallableMock(); @@ -94,11 +104,13 @@ public function shouldResolveValuesGeneratorEmpty(): void all($gen)->then($mock); } - /** @test */ + /** + * @test + */ public function shouldRejectIfAnyInputPromiseRejects(): void { - $exception2 = new Exception(); - $exception3 = new Exception(); + $exception2 = new \Exception(); + $exception3 = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -110,7 +122,9 @@ public function shouldRejectIfAnyInputPromiseRejects(): void ->then($this->expectCallableNever(), $mock); } - /** @test */ + /** + * @test + */ public function shouldRejectInfiteGeneratorOrRejectedPromises(): void { $mock = $this->createCallableMock(); @@ -128,7 +142,9 @@ public function shouldRejectInfiteGeneratorOrRejectedPromises(): void all($gen)->then(null, $mock); } - /** @test */ + /** + * @test + */ public function shouldPreserveTheOrderOfArrayWhenResolvingAsyncPromises(): void { $mock = $this->createCallableMock(); diff --git a/tests/FunctionAnyTest.php b/tests/FunctionAnyTest.php index 46b6c9a..f7393e2 100644 --- a/tests/FunctionAnyTest.php +++ b/tests/FunctionAnyTest.php @@ -2,13 +2,14 @@ namespace React\Promise; -use Exception; use React\Promise\Exception\CompositeException; use React\Promise\Exception\LengthException; class FunctionAnyTest extends TestCase { - /** @test */ + /** + * @test + */ public function shouldRejectWithLengthExceptionWithEmptyInputArray(): void { $mock = $this->createCallableMock(); @@ -17,14 +18,16 @@ public function shouldRejectWithLengthExceptionWithEmptyInputArray(): void ->method('__invoke') ->with( self::callback(fn($exception) => $exception instanceof LengthException && - 'Must contain at least 1 item but contains only 0 items.' === $exception->getMessage()) + $exception->getMessage() === 'Must contain at least 1 item but contains only 0 items.'), ); any([]) ->then($this->expectCallableNever(), $mock); } - /** @test */ + /** + * @test + */ public function shouldRejectWithLengthExceptionWithEmptyInputGenerator(): void { $mock = $this->createCallableMock(); @@ -42,7 +45,9 @@ public function shouldRejectWithLengthExceptionWithEmptyInputGenerator(): void any($gen)->then($this->expectCallableNever(), $mock); } - /** @test */ + /** + * @test + */ public function shouldResolveWithAnInputValue(): void { $mock = $this->createCallableMock(); @@ -55,7 +60,9 @@ public function shouldResolveWithAnInputValue(): void ->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveWithAPromisedInputValue(): void { $mock = $this->createCallableMock(); @@ -68,7 +75,9 @@ public function shouldResolveWithAPromisedInputValue(): void ->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveWithAnInputValueFromDeferred(): void { $mock = $this->createCallableMock(); @@ -84,7 +93,9 @@ public function shouldResolveWithAnInputValueFromDeferred(): void $deferred->resolve(1); } - /** @test */ + /** + * @test + */ public function shouldResolveValuesGenerator(): void { $mock = $this->createCallableMock(); @@ -102,7 +113,9 @@ public function shouldResolveValuesGenerator(): void any($gen)->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveValuesInfiniteGenerator(): void { $mock = $this->createCallableMock(); @@ -120,16 +133,18 @@ public function shouldResolveValuesInfiniteGenerator(): void any($gen)->then($mock); } - /** @test */ + /** + * @test + */ public function shouldRejectWithAllRejectedInputValuesIfAllInputsAreRejected(): void { - $exception1 = new Exception(); - $exception2 = new Exception(); - $exception3 = new Exception(); + $exception1 = new \Exception(); + $exception2 = new \Exception(); + $exception3 = new \Exception(); $compositeException = new CompositeException( [0 => $exception1, 1 => $exception2, 2 => $exception3], - 'All promises rejected.' + 'All promises rejected.', ); $mock = $this->createCallableMock(); @@ -142,14 +157,16 @@ public function shouldRejectWithAllRejectedInputValuesIfAllInputsAreRejected(): ->then($this->expectCallableNever(), $mock); } - /** @test */ + /** + * @test + */ public function shouldRejectWithAllRejectedInputValuesIfInputIsRejectedFromDeferred(): void { - $exception = new Exception(); + $exception = new \Exception(); $compositeException = new CompositeException( [2 => $exception], - 'All promises rejected.' + 'All promises rejected.', ); $mock = $this->createCallableMock(); @@ -165,11 +182,13 @@ public function shouldRejectWithAllRejectedInputValuesIfInputIsRejectedFromDefer $deferred->reject($exception); } - /** @test */ + /** + * @test + */ public function shouldResolveWhenFirstInputPromiseResolves(): void { - $exception2 = new Exception(); - $exception3 = new Exception(); + $exception2 = new \Exception(); + $exception3 = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -181,7 +200,9 @@ public function shouldResolveWhenFirstInputPromiseResolves(): void ->then($mock); } - /** @test */ + /** + * @test + */ public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue(): void { $mock = $this->createCallableMock(); @@ -200,7 +221,9 @@ public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue $d1->resolve(1); } - /** @test */ + /** + * @test + */ public function shouldCancelInputArrayPromises(): void { $promise1 = new Promise(function (): void {}, $this->expectCallableOnce()); @@ -209,7 +232,9 @@ public function shouldCancelInputArrayPromises(): void any([$promise1, $promise2])->cancel(); } - /** @test */ + /** + * @test + */ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfills(): void { $deferred = new Deferred($this->expectCallableNever()); diff --git a/tests/FunctionCheckTypehintTest.php b/tests/FunctionCheckTypehintTest.php index b5b609a..c41d467 100644 --- a/tests/FunctionCheckTypehintTest.php +++ b/tests/FunctionCheckTypehintTest.php @@ -2,44 +2,51 @@ namespace React\Promise; -use Exception; -use InvalidArgumentException; - class FunctionCheckTypehintTest extends TestCase { - /** @test */ + /** + * @test + */ public function shouldAcceptClosureCallbackWithTypehint(): void { - self::assertTrue(_checkTypehint(function (InvalidArgumentException $e): void {}, new InvalidArgumentException())); - self::assertFalse(_checkTypehint(function (InvalidArgumentException $e): void {}, new Exception())); + self::assertTrue(_checkTypehint(function (\InvalidArgumentException $e): void {}, new \InvalidArgumentException())); + self::assertFalse(_checkTypehint(function (\InvalidArgumentException $e): void {}, new \Exception())); } - /** @test */ + /** + * @test + */ public function shouldAcceptFunctionStringCallbackWithTypehint(): void { - self::assertTrue(_checkTypehint(new CallbackWithTypehintClass(), new InvalidArgumentException())); - self::assertFalse(_checkTypehint(new CallbackWithTypehintClass(), new Exception())); + self::assertTrue(_checkTypehint(new CallbackWithTypehintClass(), new \InvalidArgumentException())); + self::assertFalse(_checkTypehint(new CallbackWithTypehintClass(), new \Exception())); } - /** @test */ + /** + * @test + */ public function shouldAcceptInvokableObjectCallbackWithTypehint(): void { - self::assertTrue(_checkTypehint(new CallbackWithTypehintClass(), new InvalidArgumentException())); - self::assertFalse(_checkTypehint(new CallbackWithTypehintClass(), new Exception())); + self::assertTrue(_checkTypehint(new CallbackWithTypehintClass(), new \InvalidArgumentException())); + self::assertFalse(_checkTypehint(new CallbackWithTypehintClass(), new \Exception())); } - /** @test */ + /** + * @test + */ public function shouldAcceptObjectMethodCallbackWithTypehint(): void { - self::assertTrue(_checkTypehint([new CallbackWithTypehintClass(), 'testCallback'], new InvalidArgumentException())); - self::assertFalse(_checkTypehint([new CallbackWithTypehintClass(), 'testCallback'], new Exception())); + self::assertTrue(_checkTypehint([new CallbackWithTypehintClass(), 'testCallback'], new \InvalidArgumentException())); + self::assertFalse(_checkTypehint([new CallbackWithTypehintClass(), 'testCallback'], new \Exception())); } - /** @test */ + /** + * @test + */ public function shouldAcceptStaticClassCallbackWithTypehint(): void { - self::assertTrue(_checkTypehint([CallbackWithTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException())); - self::assertFalse(_checkTypehint([CallbackWithTypehintClass::class, 'testCallbackStatic'], new Exception())); + self::assertTrue(_checkTypehint([CallbackWithTypehintClass::class, 'testCallbackStatic'], new \InvalidArgumentException())); + self::assertFalse(_checkTypehint([CallbackWithTypehintClass::class, 'testCallbackStatic'], new \Exception())); } /** @@ -61,8 +68,8 @@ public function shouldAcceptClosureCallbackWithUnionTypehint(): void */ public function shouldAcceptInvokableObjectCallbackWithUnionTypehint(): void { - self::assertTrue(_checkTypehint(new CallbackWithUnionTypehintClass(), new InvalidArgumentException())); - self::assertFalse(_checkTypehint(new CallbackWithUnionTypehintClass(), new Exception())); + self::assertTrue(_checkTypehint(new CallbackWithUnionTypehintClass(), new \InvalidArgumentException())); + self::assertFalse(_checkTypehint(new CallbackWithUnionTypehintClass(), new \Exception())); } /** @@ -71,8 +78,8 @@ public function shouldAcceptInvokableObjectCallbackWithUnionTypehint(): void */ public function shouldAcceptObjectMethodCallbackWithUnionTypehint(): void { - self::assertTrue(_checkTypehint([new CallbackWithUnionTypehintClass(), 'testCallback'], new InvalidArgumentException())); - self::assertFalse(_checkTypehint([new CallbackWithUnionTypehintClass(), 'testCallback'], new Exception())); + self::assertTrue(_checkTypehint([new CallbackWithUnionTypehintClass(), 'testCallback'], new \InvalidArgumentException())); + self::assertFalse(_checkTypehint([new CallbackWithUnionTypehintClass(), 'testCallback'], new \Exception())); } /** @@ -81,8 +88,8 @@ public function shouldAcceptObjectMethodCallbackWithUnionTypehint(): void */ public function shouldAcceptStaticClassCallbackWithUnionTypehint(): void { - self::assertTrue(_checkTypehint([CallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException())); - self::assertFalse(_checkTypehint([CallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new Exception())); + self::assertTrue(_checkTypehint([CallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new \InvalidArgumentException())); + self::assertFalse(_checkTypehint([CallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new \Exception())); } /** @@ -148,42 +155,47 @@ public function shouldAcceptStaticClassCallbackWithDNFTypehint(): void self::assertTrue(_checkTypehint([CallbackWithDNFTypehintClass::class, 'testCallbackStatic'], new IterableException())); } - /** @test */ + /** + * @test + */ public function shouldAcceptClosureCallbackWithoutTypehint(): void { - self::assertTrue(_checkTypehint(function (InvalidArgumentException $e): void { - }, new InvalidArgumentException())); + self::assertTrue(_checkTypehint(function (\InvalidArgumentException $e): void {}, new \InvalidArgumentException())); } - /** @test */ + /** + * @test + */ public function shouldAcceptFunctionStringCallbackWithoutTypehint(): void { - self::assertTrue(_checkTypehint(new CallbackWithoutTypehintClass(), new InvalidArgumentException())); + self::assertTrue(_checkTypehint(new CallbackWithoutTypehintClass(), new \InvalidArgumentException())); } - /** @test */ + /** + * @test + */ public function shouldAcceptInvokableObjectCallbackWithoutTypehint(): void { - self::assertTrue(_checkTypehint(new CallbackWithoutTypehintClass(), new InvalidArgumentException())); + self::assertTrue(_checkTypehint(new CallbackWithoutTypehintClass(), new \InvalidArgumentException())); } - /** @test */ + /** + * @test + */ public function shouldAcceptObjectMethodCallbackWithoutTypehint(): void { - self::assertTrue(_checkTypehint([new CallbackWithoutTypehintClass(), 'testCallback'], new InvalidArgumentException())); + self::assertTrue(_checkTypehint([new CallbackWithoutTypehintClass(), 'testCallback'], new \InvalidArgumentException())); } - /** @test */ + /** + * @test + */ public function shouldAcceptStaticClassCallbackWithoutTypehint(): void { - self::assertTrue(_checkTypehint([CallbackWithoutTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException())); + self::assertTrue(_checkTypehint([CallbackWithoutTypehintClass::class, 'testCallbackStatic'], new \InvalidArgumentException())); } } -function testCallbackWithTypehint(InvalidArgumentException $e): void -{ -} +function testCallbackWithTypehint(\InvalidArgumentException $e): void {} -function testCallbackWithoutTypehint(): void -{ -} +function testCallbackWithoutTypehint(): void {} diff --git a/tests/FunctionRaceTest.php b/tests/FunctionRaceTest.php index 90264d0..b58886b 100644 --- a/tests/FunctionRaceTest.php +++ b/tests/FunctionRaceTest.php @@ -2,19 +2,21 @@ namespace React\Promise; -use Exception; - class FunctionRaceTest extends TestCase { - /** @test */ + /** + * @test + */ public function shouldReturnForeverPendingPromiseForEmptyInput(): void { race( - [] + [], )->then($this->expectCallableNever(), $this->expectCallableNever()); } - /** @test */ + /** + * @test + */ public function shouldResolveValuesArray(): void { $mock = $this->createCallableMock(); @@ -24,11 +26,13 @@ public function shouldResolveValuesArray(): void ->with(self::identicalTo(1)); race( - [1, 2, 3] + [1, 2, 3], )->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolvePromisesArray(): void { $mock = $this->createCallableMock(); @@ -42,7 +46,7 @@ public function shouldResolvePromisesArray(): void $d3 = new Deferred(); race( - [$d1->promise(), $d2->promise(), $d3->promise()] + [$d1->promise(), $d2->promise(), $d3->promise()], )->then($mock); $d2->resolve(2); @@ -51,7 +55,9 @@ public function shouldResolvePromisesArray(): void $d3->resolve(3); } - /** @test */ + /** + * @test + */ public function shouldResolveSparseArrayInput(): void { $mock = $this->createCallableMock(); @@ -61,11 +67,13 @@ public function shouldResolveSparseArrayInput(): void ->with(self::identicalTo(null)); race( - [null, 1, null, 2, 3] + [null, 1, null, 2, 3], )->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveValuesGenerator(): void { $mock = $this->createCallableMock(); @@ -83,7 +91,9 @@ public function shouldResolveValuesGenerator(): void race($gen)->then($mock); } - /** @test */ + /** + * @test + */ public function shouldResolveValuesInfiniteGenerator(): void { $mock = $this->createCallableMock(); @@ -101,10 +111,12 @@ public function shouldResolveValuesInfiniteGenerator(): void race($gen)->then($mock); } - /** @test */ + /** + * @test + */ public function shouldRejectIfFirstSettledPromiseRejects(): void { - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -117,7 +129,7 @@ public function shouldRejectIfFirstSettledPromiseRejects(): void $d3 = new Deferred(); race( - [$d1->promise(), $d2->promise(), $d3->promise()] + [$d1->promise(), $d2->promise(), $d3->promise()], )->then($this->expectCallableNever(), $mock); $d2->reject($exception); @@ -126,7 +138,9 @@ public function shouldRejectIfFirstSettledPromiseRejects(): void $d3->resolve(3); } - /** @test */ + /** + * @test + */ public function shouldCancelInputArrayPromises(): void { $promise1 = new Promise(function (): void {}, $this->expectCallableOnce()); @@ -135,7 +149,9 @@ public function shouldCancelInputArrayPromises(): void race([$promise1, $promise2])->cancel(); } - /** @test */ + /** + * @test + */ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfills(): void { $deferred = new Deferred($this->expectCallableNever()); @@ -146,11 +162,13 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfill race([$deferred->promise(), $promise2])->cancel(); } - /** @test */ + /** + * @test + */ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseRejects(): void { $deferred = new Deferred($this->expectCallableNever()); - $deferred->reject(new Exception()); + $deferred->reject(new \Exception()); $promise2 = new Promise(function (): void {}, $this->expectCallableNever()); diff --git a/tests/FunctionRejectTest.php b/tests/FunctionRejectTest.php index 38b7cc6..9c3be23 100644 --- a/tests/FunctionRejectTest.php +++ b/tests/FunctionRejectTest.php @@ -2,14 +2,14 @@ namespace React\Promise; -use Exception; - class FunctionRejectTest extends TestCase { - /** @test */ + /** + * @test + */ public function shouldRejectAnException(): void { - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock diff --git a/tests/FunctionResolveTest.php b/tests/FunctionResolveTest.php index 665948b..f1a2681 100644 --- a/tests/FunctionResolveTest.php +++ b/tests/FunctionResolveTest.php @@ -4,11 +4,12 @@ use React\Promise\Internal\FulfilledPromise; use React\Promise\Internal\RejectedPromise; -use Exception; class FunctionResolveTest extends TestCase { - /** @test */ + /** + * @test + */ public function shouldResolveAnImmediateValue(): void { $expected = 123; @@ -22,11 +23,13 @@ public function shouldResolveAnImmediateValue(): void resolve($expected) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function shouldResolveAFulfilledPromise(): void { $expected = 123; @@ -42,11 +45,13 @@ public function shouldResolveAFulfilledPromise(): void resolve($resolved) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function shouldResolveAThenable(): void { $thenable = new SimpleFulfilledTestThenable(); @@ -60,11 +65,13 @@ public function shouldResolveAThenable(): void resolve($thenable) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function shouldResolveACancellableThenable(): void { $thenable = new SimpleTestCancellableThenable(); @@ -75,10 +82,12 @@ public function shouldResolveACancellableThenable(): void self::assertTrue($thenable->cancelCalled); } - /** @test */ + /** + * @test + */ public function shouldRejectARejectedPromise(): void { - $exception = new Exception(); + $exception = new \Exception(); $resolved = new RejectedPromise($exception); @@ -91,11 +100,13 @@ public function shouldRejectARejectedPromise(): void resolve($resolved) ->then( $this->expectCallableNever(), - $mock + $mock, ); } - /** @test */ + /** + * @test + */ public function shouldSupportDeepNestingInPromiseChains(): void { $d = new Deferred(); @@ -108,7 +119,7 @@ public function shouldSupportDeepNestingInPromiseChains(): void $identity = fn($val) => $val; return resolve($d->promise()->then($identity))->then( - fn($val) => !$val + fn($val) => !$val, ); }))); @@ -121,7 +132,9 @@ public function shouldSupportDeepNestingInPromiseChains(): void $result->then($mock); } - /** @test */ + /** + * @test + */ public function shouldSupportVeryDeepNestedPromises(): void { if (PHP_VERSION_ID < 70200 && ini_get('xdebug.max_nesting_level') !== false) { diff --git a/tests/Internal/CancellationQueueTest.php b/tests/Internal/CancellationQueueTest.php index e8fd58e..694248a 100644 --- a/tests/Internal/CancellationQueueTest.php +++ b/tests/Internal/CancellationQueueTest.php @@ -2,7 +2,6 @@ namespace React\Promise\Internal; -use Exception; use React\Promise\Deferred; use React\Promise\SimpleTestCancellable; use React\Promise\SimpleTestCancellableThenable; @@ -10,7 +9,9 @@ class CancellationQueueTest extends TestCase { - /** @test */ + /** + * @test + */ public function acceptsSimpleCancellableThenable(): void { $p = new SimpleTestCancellableThenable(); @@ -23,7 +24,9 @@ public function acceptsSimpleCancellableThenable(): void self::assertTrue($p->cancelCalled); } - /** @test */ + /** + * @test + */ public function ignoresSimpleCancellable(): void { $p = new SimpleTestCancellable(); @@ -36,7 +39,9 @@ public function ignoresSimpleCancellable(): void self::assertFalse($p->cancelCalled); } - /** @test */ + /** + * @test + */ public function callsCancelOnPromisesEnqueuedBeforeStart(): void { $d1 = $this->getCancellableDeferred(); @@ -49,7 +54,9 @@ public function callsCancelOnPromisesEnqueuedBeforeStart(): void $cancellationQueue(); } - /** @test */ + /** + * @test + */ public function callsCancelOnPromisesEnqueuedAfterStart(): void { $d1 = $this->getCancellableDeferred(); @@ -63,7 +70,9 @@ public function callsCancelOnPromisesEnqueuedAfterStart(): void $cancellationQueue->enqueue($d1->promise()); } - /** @test */ + /** + * @test + */ public function doesNotCallCancelTwiceWhenStartedTwice(): void { $d = $this->getCancellableDeferred(); @@ -80,13 +89,13 @@ public function doesNotCallCancelTwiceWhenStartedTwice(): void */ public function rethrowsExceptionsThrownFromCancel(): void { - $this->expectException(Exception::class); + $this->expectException(\Exception::class); $this->expectExceptionMessage('test'); $mock = $this->createCallableMock(); $mock ->expects(self::once()) ->method('__invoke') - ->will(self::throwException(new Exception('test'))); + ->will(self::throwException(new \Exception('test'))); $promise = new SimpleTestCancellableThenable($mock); diff --git a/tests/Internal/FulfilledPromiseTest.php b/tests/Internal/FulfilledPromiseTest.php index 3df4eb8..2aa745d 100644 --- a/tests/Internal/FulfilledPromiseTest.php +++ b/tests/Internal/FulfilledPromiseTest.php @@ -2,8 +2,6 @@ namespace React\Promise\Internal; -use InvalidArgumentException; -use LogicException; use React\Promise\PromiseAdapter\CallbackPromiseAdapter; use React\Promise\PromiseTest\PromiseFulfilledTestTrait; use React\Promise\PromiseTest\PromiseSettledTestTrait; @@ -14,8 +12,8 @@ */ class FulfilledPromiseTest extends TestCase { - use PromiseSettledTestTrait, - PromiseFulfilledTestTrait; + use PromiseSettledTestTrait; + use PromiseFulfilledTestTrait; /** * @return CallbackPromiseAdapter @@ -28,7 +26,7 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm return new CallbackPromiseAdapter([ 'promise' => function () use (&$promise) { if (!$promise) { - throw new LogicException('FulfilledPromise must be resolved before obtaining the promise'); + throw new \LogicException('FulfilledPromise must be resolved before obtaining the promise'); } return $promise; @@ -39,7 +37,7 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm } }, 'reject' => function (): void { - throw new LogicException('You cannot call reject() for React\Promise\FulfilledPromise'); + throw new \LogicException('You cannot call reject() for React\Promise\FulfilledPromise'); }, 'settle' => function ($value = null) use (&$promise): void { if (!$promise) { @@ -54,7 +52,7 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm */ public function shouldThrowExceptionIfConstructedWithAPromise(): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException(\InvalidArgumentException::class); new FulfilledPromise(new FulfilledPromise()); } } diff --git a/tests/Internal/RejectedPromiseTest.php b/tests/Internal/RejectedPromiseTest.php index c755498..0aa5573 100644 --- a/tests/Internal/RejectedPromiseTest.php +++ b/tests/Internal/RejectedPromiseTest.php @@ -2,8 +2,6 @@ namespace React\Promise\Internal; -use Exception; -use LogicException; use React\Promise\PromiseAdapter\CallbackPromiseAdapter; use React\Promise\PromiseTest\PromiseRejectedTestTrait; use React\Promise\PromiseTest\PromiseSettledTestTrait; @@ -11,8 +9,8 @@ class RejectedPromiseTest extends TestCase { - use PromiseSettledTestTrait, - PromiseRejectedTestTrait; + use PromiseSettledTestTrait; + use PromiseRejectedTestTrait; /** * @return CallbackPromiseAdapter @@ -25,13 +23,13 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm return new CallbackPromiseAdapter([ 'promise' => function () use (&$promise) { if (!$promise) { - throw new LogicException('RejectedPromise must be rejected before obtaining the promise'); + throw new \LogicException('RejectedPromise must be rejected before obtaining the promise'); } return $promise; }, 'resolve' => function (): void { - throw new LogicException('You cannot call resolve() for React\Promise\RejectedPromise'); + throw new \LogicException('You cannot call resolve() for React\Promise\RejectedPromise'); }, 'reject' => function (\Throwable $reason) use (&$promise): void { if (!$promise) { @@ -40,8 +38,8 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm }, 'settle' => function ($reason = '') use (&$promise): void { if (!$promise) { - if (!$reason instanceof Exception) { - $reason = new Exception((string) $reason); + if (!$reason instanceof \Exception) { + $reason = new \Exception((string) $reason); } $promise = new RejectedPromise($reason); diff --git a/tests/PromiseAdapter/CallbackPromiseAdapter.php b/tests/PromiseAdapter/CallbackPromiseAdapter.php index 225814a..421d7f5 100644 --- a/tests/PromiseAdapter/CallbackPromiseAdapter.php +++ b/tests/PromiseAdapter/CallbackPromiseAdapter.php @@ -13,9 +13,7 @@ class CallbackPromiseAdapter implements PromiseAdapterInterface /** * @param callable[] $callbacks */ - public function __construct(private array $callbacks) - { - } + public function __construct(private array $callbacks) {} /** * @return PromiseInterface diff --git a/tests/PromiseAdapter/PromiseAdapterInterface.php b/tests/PromiseAdapter/PromiseAdapterInterface.php index 1699538..82023b7 100644 --- a/tests/PromiseAdapter/PromiseAdapterInterface.php +++ b/tests/PromiseAdapter/PromiseAdapterInterface.php @@ -15,6 +15,8 @@ interface PromiseAdapterInterface public function promise(): PromiseInterface; public function resolve(mixed $value): void; + public function reject(): void; + public function settle(): void; } diff --git a/tests/PromiseTest.php b/tests/PromiseTest.php index d459b40..5a21fc9 100644 --- a/tests/PromiseTest.php +++ b/tests/PromiseTest.php @@ -2,7 +2,6 @@ namespace React\Promise; -use Exception; use React\Promise\PromiseAdapter\CallbackPromiseAdapter; /** @@ -35,10 +34,12 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm ]); } - /** @test */ + /** + * @test + */ public function shouldRejectIfResolverThrowsException(): void { - $exception = new Exception('foo'); + $exception = new \Exception('foo'); $promise = new Promise(function () use ($exception): void { throw $exception; @@ -54,7 +55,9 @@ public function shouldRejectIfResolverThrowsException(): void ->then($this->expectCallableNever(), $mock); } - /** @test */ + /** + * @test + */ public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithException(): void { gc_collect_cycles(); @@ -66,7 +69,9 @@ public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithE $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptionWithoutResolver(): void { gc_collect_cycles(); @@ -81,7 +86,9 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithException(): void { gc_collect_cycles(); @@ -96,11 +103,13 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithExc $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException(): void { gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject): void { }, function ($resolve, $reject): void { + $promise = new Promise(function ($resolve, $reject): void {}, function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $promise->cancel(); @@ -109,11 +118,13 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithEx $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException(): void { gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject): void { }, function ($resolve, $reject): void { + $promise = new Promise(function ($resolve, $reject): void {}, function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $promise->then()->then()->then()->cancel(); @@ -122,7 +133,9 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejects $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsException(): void { gc_collect_cycles(); @@ -137,44 +150,52 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise(): void { gc_collect_cycles(); - $promise = new Promise(function (): void { }); + $promise = new Promise(function (): void {}); unset($promise); $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithThenFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function (): void { }); + $promise = new Promise(function (): void {}); $promise->then()->then()->then(); unset($promise); $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithCatchFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function (): void { }); - $promise->catch(function (): void { }); + $promise = new Promise(function (): void {}); + $promise->catch(function (): void {}); unset($promise); $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithFinallyFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function (): void { }); - $promise->finally(function (): void { }); + $promise = new Promise(function (): void {}); + $promise->finally(function (): void {}); unset($promise); $this->assertSame(0, gc_collect_cycles()); @@ -187,8 +208,8 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithOtherwiseFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function (): void { }); - $promise->otherwise(function (): void { }); + $promise = new Promise(function (): void {}); + $promise->otherwise(function (): void {}); unset($promise); $this->assertSame(0, gc_collect_cycles()); @@ -201,19 +222,21 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithAlwaysFollowers(): void { gc_collect_cycles(); - $promise = new Promise(function (): void { }); - $promise->always(function (): void { }); + $promise = new Promise(function (): void {}); + $promise->always(function (): void {}); unset($promise); $this->assertSame(0, gc_collect_cycles()); } - /** @test */ + /** + * @test + */ public function shouldFulfillIfFullfilledWithSimplePromise(): void { gc_collect_cycles(); $promise = new Promise(function (): void { - throw new Exception('foo'); + throw new \Exception('foo'); }); $promise->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection diff --git a/tests/PromiseTest/CancelTestTrait.php b/tests/PromiseTest/CancelTestTrait.php index 6e77e85..fe0a8c6 100644 --- a/tests/PromiseTest/CancelTestTrait.php +++ b/tests/PromiseTest/CancelTestTrait.php @@ -2,7 +2,6 @@ namespace React\Promise\PromiseTest; -use Exception; use React\Promise; use React\Promise\PromiseAdapter\PromiseAdapterInterface; @@ -10,7 +9,9 @@ trait CancelTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** @test */ + /** + * @test + */ public function cancelShouldCallCancellerWithResolverArguments(): void { $args = []; @@ -25,7 +26,9 @@ public function cancelShouldCallCancellerWithResolverArguments(): void self::assertTrue(is_callable($args[1])); } - /** @test */ + /** + * @test + */ public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed(): void { $args = null; @@ -38,7 +41,9 @@ public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed(): void self::assertSame(0, $args); } - /** @test */ + /** + * @test + */ public function cancelShouldFulfillPromiseIfCancellerFulfills(): void { $adapter = $this->getPromiseTestAdapter(function ($resolve): void { @@ -57,10 +62,12 @@ public function cancelShouldFulfillPromiseIfCancellerFulfills(): void $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldRejectPromiseIfCancellerRejects(): void { - $exception = new Exception(); + $exception = new \Exception(); $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject) use ($exception): void { $reject($exception); @@ -78,10 +85,12 @@ public function cancelShouldRejectPromiseIfCancellerRejects(): void $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldRejectPromiseWithExceptionIfCancellerThrows(): void { - $e = new Exception(); + $e = new \Exception(); $adapter = $this->getPromiseTestAdapter(function () use ($e): void { throw $e; @@ -99,7 +108,9 @@ public function cancelShouldRejectPromiseWithExceptionIfCancellerThrows(): void $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves(): void { $mock = $this->createCallableMock(); @@ -116,7 +127,9 @@ public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves(): void $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldHaveNoEffectIfCancellerDoesNothing(): void { $adapter = $this->getPromiseTestAdapter(function (): void {}); @@ -128,7 +141,9 @@ public function cancelShouldHaveNoEffectIfCancellerDoesNothing(): void $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldCallCancellerFromDeepNestedPromiseChain(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -145,7 +160,9 @@ public function cancelShouldCallCancellerFromDeepNestedPromiseChain(): void $promise->cancel(); } - /** @test */ + /** + * @test + */ public function cancelCalledOnChildrenSouldOnlyCancelWhenAllChildrenCancelled(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -160,7 +177,9 @@ public function cancelCalledOnChildrenSouldOnlyCancelWhenAllChildrenCancelled(): $child1->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldTriggerCancellerWhenAllChildrenCancel(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -176,7 +195,9 @@ public function cancelShouldTriggerCancellerWhenAllChildrenCancel(): void $child2->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldNotTriggerCancellerWhenCancellingOneChildrenMultipleTimes(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -192,7 +213,9 @@ public function cancelShouldNotTriggerCancellerWhenCancellingOneChildrenMultiple $child1->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldTriggerCancellerOnlyOnceWhenCancellingMultipleTimes(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -201,7 +224,9 @@ public function cancelShouldTriggerCancellerOnlyOnceWhenCancellingMultipleTimes( $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldAlwaysTriggerCancellerWhenCalledOnRootPromise(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -216,7 +241,9 @@ public function cancelShouldAlwaysTriggerCancellerWhenCalledOnRootPromise(): voi $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldTriggerCancellerWhenFollowerCancels(): void { $adapter1 = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -231,7 +258,9 @@ public function cancelShouldTriggerCancellerWhenFollowerCancels(): void $follower->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldNotTriggerCancellerWhenCancellingOnlyOneFollower(): void { $adapter1 = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -249,7 +278,9 @@ public function cancelShouldNotTriggerCancellerWhenCancellingOnlyOneFollower(): $follower1->cancel(); } - /** @test */ + /** + * @test + */ public function cancelCalledOnFollowerShouldOnlyCancelWhenAllChildrenAndFollowerCancelled(): void { $adapter1 = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -267,7 +298,9 @@ public function cancelCalledOnFollowerShouldOnlyCancelWhenAllChildrenAndFollower $child->cancel(); } - /** @test */ + /** + * @test + */ public function cancelShouldNotTriggerCancellerWhenCancellingFollowerButNotChildren(): void { $adapter1 = $this->getPromiseTestAdapter($this->expectCallableNever()); diff --git a/tests/PromiseTest/FullTestTrait.php b/tests/PromiseTest/FullTestTrait.php index 5a331dd..e0ffc23 100644 --- a/tests/PromiseTest/FullTestTrait.php +++ b/tests/PromiseTest/FullTestTrait.php @@ -4,11 +4,11 @@ trait FullTestTrait { - use PromisePendingTestTrait, - PromiseSettledTestTrait, - PromiseFulfilledTestTrait, - PromiseRejectedTestTrait, - ResolveTestTrait, - RejectTestTrait, - CancelTestTrait; + use PromisePendingTestTrait; + use PromiseSettledTestTrait; + use PromiseFulfilledTestTrait; + use PromiseRejectedTestTrait; + use ResolveTestTrait; + use RejectTestTrait; + use CancelTestTrait; } diff --git a/tests/PromiseTest/PromiseFulfilledTestTrait.php b/tests/PromiseTest/PromiseFulfilledTestTrait.php index c128b6d..182d86f 100644 --- a/tests/PromiseTest/PromiseFulfilledTestTrait.php +++ b/tests/PromiseTest/PromiseFulfilledTestTrait.php @@ -2,10 +2,9 @@ namespace React\Promise\PromiseTest; -use Exception; use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; -use stdClass; + use function React\Promise\reject; use function React\Promise\resolve; @@ -13,7 +12,9 @@ trait PromiseFulfilledTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** @test */ + /** + * @test + */ public function fulfilledPromiseShouldBeImmutable(): void { $adapter = $this->getPromiseTestAdapter(); @@ -30,11 +31,13 @@ public function fulfilledPromiseShouldBeImmutable(): void $adapter->promise() ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function fulfilledPromiseShouldInvokeNewlyAddedCallback(): void { $adapter = $this->getPromiseTestAdapter(); @@ -51,7 +54,9 @@ public function fulfilledPromiseShouldInvokeNewlyAddedCallback(): void ->then($mock, $this->expectCallableNever()); } - /** @test */ + /** + * @test + */ public function thenShouldForwardResultWhenCallbackIsNull(): void { $adapter = $this->getPromiseTestAdapter(); @@ -66,15 +71,17 @@ public function thenShouldForwardResultWhenCallbackIsNull(): void $adapter->promise() ->then( null, - $this->expectCallableNever() + $this->expectCallableNever(), ) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function thenShouldForwardCallbackResultToNextCallback(): void { $adapter = $this->getPromiseTestAdapter(); @@ -89,15 +96,17 @@ public function thenShouldForwardCallbackResultToNextCallback(): void $adapter->promise() ->then( fn($val) => $val + 1, - $this->expectCallableNever() + $this->expectCallableNever(), ) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function thenShouldForwardPromisedCallbackResultValueToNextCallback(): void { $adapter = $this->getPromiseTestAdapter(); @@ -112,20 +121,22 @@ public function thenShouldForwardPromisedCallbackResultValueToNextCallback(): vo $adapter->promise() ->then( fn($val) => resolve($val + 1), - $this->expectCallableNever() + $this->expectCallableNever(), ) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackReturnsARejection(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -137,20 +148,22 @@ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackReturnsARejec $adapter->promise() ->then( fn() => reject($exception), - $this->expectCallableNever() + $this->expectCallableNever(), ) ->then( $this->expectCallableNever(), - $mock + $mock, ); } - /** @test */ + /** + * @test + */ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackThrows(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -168,11 +181,11 @@ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackThrows(): voi $adapter->promise() ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ) ->then( $this->expectCallableNever(), - $mock2 + $mock2, ); } @@ -204,7 +217,9 @@ public function thenShouldContinueToExecuteCallbacksWhenPriorCallbackSuspendsFib $adapter->promise()->then($mock); } - /** @test */ + /** + * @test + */ public function cancelShouldHaveNoEffectForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -214,7 +229,9 @@ public function cancelShouldHaveNoEffectForFulfilledPromise(): void $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function catchShouldNotInvokeRejectionHandlerForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -223,12 +240,14 @@ public function catchShouldNotInvokeRejectionHandlerForFulfilledPromise(): void $adapter->promise()->catch($this->expectCallableNever()); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressValueForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -242,12 +261,14 @@ public function finallyShouldNotSuppressValueForFulfilledPromise(): void ->then($mock); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -262,12 +283,14 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFul ->then($mock); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -282,12 +305,14 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfil ->then($mock); } - /** @test */ + /** + * @test + */ public function finallyShouldRejectWhenHandlerThrowsForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -303,12 +328,14 @@ public function finallyShouldRejectWhenHandlerThrowsForFulfilledPromise(): void ->then(null, $mock); } - /** @test */ + /** + * @test + */ public function finallyShouldRejectWhenHandlerRejectsForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -342,7 +369,7 @@ public function alwaysShouldNotSuppressValueForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -364,7 +391,7 @@ public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulf { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -387,7 +414,7 @@ public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfill { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -410,7 +437,7 @@ public function alwaysShouldRejectWhenHandlerThrowsForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -434,7 +461,7 @@ public function alwaysShouldRejectWhenHandlerRejectsForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock diff --git a/tests/PromiseTest/PromisePendingTestTrait.php b/tests/PromiseTest/PromisePendingTestTrait.php index f0ae13c..befd319 100644 --- a/tests/PromiseTest/PromisePendingTestTrait.php +++ b/tests/PromiseTest/PromisePendingTestTrait.php @@ -9,7 +9,9 @@ trait PromisePendingTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** @test */ + /** + * @test + */ public function thenShouldReturnAPromiseForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -17,7 +19,9 @@ public function thenShouldReturnAPromiseForPendingPromise(): void self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->then()); } - /** @test */ + /** + * @test + */ public function thenShouldReturnAllowNullForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -25,7 +29,9 @@ public function thenShouldReturnAllowNullForPendingPromise(): void self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->then(null, null)); } - /** @test */ + /** + * @test + */ public function catchShouldNotInvokeRejectionHandlerForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -34,7 +40,9 @@ public function catchShouldNotInvokeRejectionHandlerForPendingPromise(): void $adapter->promise()->catch($this->expectCallableNever()); } - /** @test */ + /** + * @test + */ public function finallyShouldReturnAPromiseForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); diff --git a/tests/PromiseTest/PromiseRejectedTestTrait.php b/tests/PromiseTest/PromiseRejectedTestTrait.php index b12da46..7cfc20d 100644 --- a/tests/PromiseTest/PromiseRejectedTestTrait.php +++ b/tests/PromiseTest/PromiseRejectedTestTrait.php @@ -2,10 +2,9 @@ namespace React\Promise\PromiseTest; -use Exception; -use InvalidArgumentException; use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; + use function React\Promise\reject; use function React\Promise\resolve; @@ -13,13 +12,15 @@ trait PromiseRejectedTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** @test */ + /** + * @test + */ public function rejectedPromiseShouldBeImmutable(): void { $adapter = $this->getPromiseTestAdapter(); - $exception1 = new Exception(); - $exception2 = new Exception(); + $exception1 = new \Exception(); + $exception2 = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -33,16 +34,18 @@ public function rejectedPromiseShouldBeImmutable(): void $adapter->promise() ->then( $this->expectCallableNever(), - $mock + $mock, ); } - /** @test */ + /** + * @test + */ public function rejectedPromiseShouldInvokeNewlyAddedCallback(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $adapter->reject($exception); @@ -56,7 +59,9 @@ public function rejectedPromiseShouldInvokeNewlyAddedCallback(): void ->then($this->expectCallableNever(), $mock); } - /** @test */ + /** + * @test + */ public function shouldForwardUndefinedRejectionValue(): void { $adapter = $this->getPromiseTestAdapter(); @@ -67,7 +72,7 @@ public function shouldForwardUndefinedRejectionValue(): void ->method('__invoke') ->with(null); - $adapter->reject(new Exception()); + $adapter->reject(new \Exception()); $adapter->promise() ->then( $this->expectCallableNever(), @@ -76,15 +81,17 @@ function (): void { // to resolve mode, even though it returns undefined. // The ONLY way to propagate a rejection is to re-throw or // return a rejected promise; - } + }, ) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackDoesNotExplicitlyPropagate(): void { $adapter = $this->getPromiseTestAdapter(); @@ -95,19 +102,21 @@ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackDoesNotExplicitlyP ->method('__invoke') ->with($this->identicalTo(2)); - $adapter->reject(new Exception()); + $adapter->reject(new \Exception()); $adapter->promise() ->then( $this->expectCallableNever(), - fn() => 2 + fn() => 2, ) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackReturnsAResolution(): void { $adapter = $this->getPromiseTestAdapter(); @@ -118,24 +127,26 @@ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackReturnsAResolution ->method('__invoke') ->with($this->identicalTo(2)); - $adapter->reject(new Exception()); + $adapter->reject(new \Exception()); $adapter->promise() ->then( $this->expectCallableNever(), - fn() => resolve(2) + fn() => resolve(2), ) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); } - /** @test */ + /** + * @test + */ public function shouldPropagateRejectionsWhenErrbackThrows(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -149,24 +160,26 @@ public function shouldPropagateRejectionsWhenErrbackThrows(): void ->method('__invoke') ->with($this->identicalTo($exception)); - $adapter->reject(new Exception()); + $adapter->reject(new \Exception()); $adapter->promise() ->then( $this->expectCallableNever(), - $mock + $mock, ) ->then( $this->expectCallableNever(), - $mock2 + $mock2, ); } - /** @test */ + /** + * @test + */ public function shouldPropagateRejectionsWhenErrbackReturnsARejection(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -174,24 +187,26 @@ public function shouldPropagateRejectionsWhenErrbackReturnsARejection(): void ->method('__invoke') ->with($this->identicalTo($exception)); - $adapter->reject(new Exception()); + $adapter->reject(new \Exception()); $adapter->promise() ->then( $this->expectCallableNever(), - fn() => reject($exception) + fn() => reject($exception), ) ->then( $this->expectCallableNever(), - $mock + $mock, ); } - /** @test */ + /** + * @test + */ public function catchShouldInvokeRejectionHandlerForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -203,12 +218,14 @@ public function catchShouldInvokeRejectionHandlerForRejectedPromise(): void $adapter->promise()->catch($mock); } - /** @test */ + /** + * @test + */ public function catchShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExceptionForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -223,12 +240,14 @@ public function catchShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExcept }); } - /** @test */ + /** + * @test + */ public function catchShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new InvalidArgumentException(); + $exception = new \InvalidArgumentException(); $mock = $this->createCallableMock(); $mock @@ -238,33 +257,37 @@ public function catchShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejec $adapter->reject($exception); $adapter->promise() - ->catch(function (InvalidArgumentException $reason) use ($mock): void { + ->catch(function (\InvalidArgumentException $reason) use ($mock): void { $mock($reason); }); } - /** @test */ + /** + * @test + */ public function catchShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchTypehintForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->expectCallableNever(); $adapter->reject($exception); $adapter->promise() - ->catch(function (InvalidArgumentException $reason) use ($mock): void { + ->catch(function (\InvalidArgumentException $reason) use ($mock): void { $mock($reason); })->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressRejectionForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -278,12 +301,14 @@ public function finallyShouldNotSuppressRejectionForRejectedPromise(): void ->then(null, $mock); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -299,12 +324,14 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseFo ->then(null, $mock); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -320,13 +347,15 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRe ->then(null, $mock); } - /** @test */ + /** + * @test + */ public function finallyShouldRejectWhenHandlerThrowsForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception1 = new Exception(); - $exception2 = new Exception(); + $exception1 = new \Exception(); + $exception2 = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -342,13 +371,15 @@ public function finallyShouldRejectWhenHandlerThrowsForRejectedPromise(): void ->then(null, $mock); } - /** @test */ + /** + * @test + */ public function finallyShouldRejectWhenHandlerRejectsForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception1 = new Exception(); - $exception2 = new Exception(); + $exception1 = new \Exception(); + $exception2 = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -362,12 +393,14 @@ public function finallyShouldRejectWhenHandlerRejectsForRejectedPromise(): void ->then(null, $mock); } - /** @test */ + /** + * @test + */ public function cancelShouldHaveNoEffectForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); - $adapter->reject(new Exception()); + $adapter->reject(new \Exception()); $adapter->promise()->cancel(); } @@ -380,7 +413,7 @@ public function otherwiseShouldInvokeRejectionHandlerForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -400,7 +433,7 @@ public function otherwiseShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnEx { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -423,7 +456,7 @@ public function otherwiseShouldInvokeRejectionHandlerIfReasonMatchesTypehintForR { $adapter = $this->getPromiseTestAdapter(); - $exception = new InvalidArgumentException(); + $exception = new \InvalidArgumentException(); $mock = $this->createCallableMock(); $mock @@ -433,7 +466,7 @@ public function otherwiseShouldInvokeRejectionHandlerIfReasonMatchesTypehintForR $adapter->reject($exception); $adapter->promise() - ->otherwise(function (InvalidArgumentException $reason) use ($mock): void { + ->otherwise(function (\InvalidArgumentException $reason) use ($mock): void { $mock($reason); }); } @@ -446,13 +479,13 @@ public function otherwiseShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchType { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->expectCallableNever(); $adapter->reject($exception); $adapter->promise() - ->otherwise(function (InvalidArgumentException $reason) use ($mock): void { + ->otherwise(function (\InvalidArgumentException $reason) use ($mock): void { $mock($reason); })->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection } @@ -465,7 +498,7 @@ public function alwaysShouldNotSuppressRejectionForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -487,20 +520,20 @@ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseFor { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock - ->expects($this->once()) - ->method('__invoke') - ->with($this->identicalTo($exception)); + ->expects($this->once()) + ->method('__invoke') + ->with($this->identicalTo($exception)); $adapter->reject($exception); $adapter->promise() - ->finally(fn(): int => - // @phpstan-ignore-line - 1) - ->then(null, $mock); + ->finally(fn(): int => + // @phpstan-ignore-line + 1) + ->then(null, $mock); } /** @@ -511,7 +544,7 @@ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRej { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -535,8 +568,8 @@ public function alwaysShouldRejectWhenHandlerThrowsForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception1 = new Exception(); - $exception2 = new Exception(); + $exception1 = new \Exception(); + $exception2 = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -560,8 +593,8 @@ public function alwaysShouldRejectWhenHandlerRejectsForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception1 = new Exception(); - $exception2 = new Exception(); + $exception1 = new \Exception(); + $exception2 = new \Exception(); $mock = $this->createCallableMock(); $mock diff --git a/tests/PromiseTest/PromiseSettledTestTrait.php b/tests/PromiseTest/PromiseSettledTestTrait.php index 0ac64ac..3a33bdc 100644 --- a/tests/PromiseTest/PromiseSettledTestTrait.php +++ b/tests/PromiseTest/PromiseSettledTestTrait.php @@ -10,7 +10,9 @@ trait PromiseSettledTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** @test */ + /** + * @test + */ public function thenShouldReturnAPromiseForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -23,7 +25,9 @@ public function thenShouldReturnAPromiseForSettledPromise(): void } } - /** @test */ + /** + * @test + */ public function thenShouldReturnAllowNullForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -36,7 +40,9 @@ public function thenShouldReturnAllowNullForSettledPromise(): void } } - /** @test */ + /** + * @test + */ public function cancelShouldHaveNoEffectForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -46,7 +52,9 @@ public function cancelShouldHaveNoEffectForSettledPromise(): void $adapter->promise()->cancel(); } - /** @test */ + /** + * @test + */ public function finallyShouldReturnAPromiseForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter(); diff --git a/tests/PromiseTest/RejectTestTrait.php b/tests/PromiseTest/RejectTestTrait.php index 6cd3854..3e08e91 100644 --- a/tests/PromiseTest/RejectTestTrait.php +++ b/tests/PromiseTest/RejectTestTrait.php @@ -2,11 +2,9 @@ namespace React\Promise\PromiseTest; -use Exception; -use React\Promise; -use React\Promise\Deferred; use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; + use function React\Promise\reject; use function React\Promise\resolve; @@ -14,12 +12,14 @@ trait RejectTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** @test */ + /** + * @test + */ public function rejectShouldRejectWithAnException(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -33,12 +33,14 @@ public function rejectShouldRejectWithAnException(): void $adapter->reject($exception); } - /** @test */ + /** + * @test + */ public function rejectShouldForwardReasonWhenCallbackIsNull(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -48,24 +50,26 @@ public function rejectShouldForwardReasonWhenCallbackIsNull(): void $adapter->promise() ->then( - $this->expectCallableNever() + $this->expectCallableNever(), ) ->then( $this->expectCallableNever(), - $mock + $mock, ); $adapter->reject($exception); } - /** @test */ + /** + * @test + */ public function rejectShouldMakePromiseImmutable(): void { $adapter = $this->getPromiseTestAdapter(); - $exception1 = new Exception(); - $exception2 = new Exception(); - $exception3 = new Exception(); + $exception1 = new \Exception(); + $exception2 = new \Exception(); + $exception3 = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -81,19 +85,21 @@ public function rejectShouldMakePromiseImmutable(): void }) ->then( $this->expectCallableNever(), - $mock + $mock, ); $adapter->reject($exception1); $adapter->reject($exception2); } - /** @test */ + /** + * @test + */ public function rejectShouldInvokeCatchHandler(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -107,12 +113,14 @@ public function rejectShouldInvokeCatchHandler(): void $adapter->reject($exception); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressRejection(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -127,12 +135,14 @@ public function finallyShouldNotSuppressRejection(): void $adapter->reject($exception); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -148,12 +158,14 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromise() $adapter->reject($exception); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -169,12 +181,14 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromise(): v $adapter->reject($exception); } - /** @test */ + /** + * @test + */ public function finallyShouldRejectWhenHandlerThrowsForRejection(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -191,12 +205,14 @@ public function finallyShouldRejectWhenHandlerThrowsForRejection(): void $adapter->reject($exception); } - /** @test */ + /** + * @test + */ public function finallyShouldRejectWhenHandlerRejectsForRejection(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock diff --git a/tests/PromiseTest/ResolveTestTrait.php b/tests/PromiseTest/ResolveTestTrait.php index f2f6af1..66e0ab6 100644 --- a/tests/PromiseTest/ResolveTestTrait.php +++ b/tests/PromiseTest/ResolveTestTrait.php @@ -2,12 +2,9 @@ namespace React\Promise\PromiseTest; -use Exception; -use LogicException; -use React\Promise; use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; -use stdClass; + use function React\Promise\reject; use function React\Promise\resolve; @@ -15,7 +12,9 @@ trait ResolveTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** @test */ + /** + * @test + */ public function resolveShouldResolve(): void { $adapter = $this->getPromiseTestAdapter(); @@ -32,7 +31,9 @@ public function resolveShouldResolve(): void $adapter->resolve(1); } - /** @test */ + /** + * @test + */ public function resolveShouldResolveWithPromisedValue(): void { $adapter = $this->getPromiseTestAdapter(); @@ -49,12 +50,14 @@ public function resolveShouldResolveWithPromisedValue(): void $adapter->resolve(resolve(1)); } - /** @test */ + /** + * @test + */ public function resolveShouldRejectWhenResolvedWithRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -68,7 +71,9 @@ public function resolveShouldRejectWhenResolvedWithRejectedPromise(): void $adapter->resolve(reject($exception)); } - /** @test */ + /** + * @test + */ public function resolveShouldForwardValueWhenCallbackIsNull(): void { $adapter = $this->getPromiseTestAdapter(); @@ -82,17 +87,19 @@ public function resolveShouldForwardValueWhenCallbackIsNull(): void $adapter->promise() ->then( null, - $this->expectCallableNever() + $this->expectCallableNever(), ) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); $adapter->resolve(1); } - /** @test */ + /** + * @test + */ public function resolveShouldMakePromiseImmutable(): void { $adapter = $this->getPromiseTestAdapter(); @@ -111,7 +118,7 @@ public function resolveShouldMakePromiseImmutable(): void }) ->then( $mock, - $this->expectCallableNever() + $this->expectCallableNever(), ); $adapter->resolve(1); @@ -129,12 +136,12 @@ public function resolveShouldRejectWhenResolvedWithItself(): void $mock ->expects($this->once()) ->method('__invoke') - ->with(new LogicException('Cannot resolve a promise with itself.')); + ->with(new \LogicException('Cannot resolve a promise with itself.')); $adapter->promise() ->then( $this->expectCallableNever(), - $mock + $mock, ); $adapter->resolve($adapter->promise()); @@ -152,7 +159,7 @@ public function resolveShouldRejectWhenResolvedWithAPromiseWhichFollowsItself(): $mock ->expects($this->once()) ->method('__invoke') - ->with(new LogicException('Cannot resolve a promise with itself.')); + ->with(new \LogicException('Cannot resolve a promise with itself.')); $promise1 = $adapter1->promise(); @@ -160,19 +167,21 @@ public function resolveShouldRejectWhenResolvedWithAPromiseWhichFollowsItself(): $promise2->then( $this->expectCallableNever(), - $mock + $mock, ); $adapter1->resolve($promise2); $adapter2->resolve($promise1); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressValue(): void { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -187,12 +196,14 @@ public function finallyShouldNotSuppressValue(): void $adapter->resolve($value); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -208,12 +219,14 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromise(): vo $adapter->resolve($value); } - /** @test */ + /** + * @test + */ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromise(): void { $adapter = $this->getPromiseTestAdapter(); - $value = new stdClass(); + $value = new \stdClass(); $mock = $this->createCallableMock(); $mock @@ -230,12 +243,14 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromise(): void $adapter->resolve($value); } - /** @test */ + /** + * @test + */ public function finallyShouldRejectWhenHandlerThrowsForFulfillment(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock @@ -252,12 +267,14 @@ public function finallyShouldRejectWhenHandlerThrowsForFulfillment(): void $adapter->resolve(1); } - /** @test */ + /** + * @test + */ public function finallyShouldRejectWhenHandlerRejectsForFulfillment(): void { $adapter = $this->getPromiseTestAdapter(); - $exception = new Exception(); + $exception = new \Exception(); $mock = $this->createCallableMock(); $mock diff --git a/tests/TestCase.php b/tests/TestCase.php index 108e8ef..c01a4a8 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,7 +2,6 @@ namespace React\Promise; -use PHPUnit\Framework\MockObject\MockBuilder; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase as BaseTestCase; @@ -35,7 +34,9 @@ public function expectCallableNever(): callable return $mock; } - /** @return MockObject&callable */ + /** + * @return MockObject&callable + */ protected function createCallableMock(): MockObject { $builder = $this->getMockBuilder(\stdClass::class); diff --git a/tests/fixtures/CallbackWithIntersectionTypehintClass.php b/tests/fixtures/CallbackWithIntersectionTypehintClass.php index 5bdb669..8228f27 100644 --- a/tests/fixtures/CallbackWithIntersectionTypehintClass.php +++ b/tests/fixtures/CallbackWithIntersectionTypehintClass.php @@ -2,17 +2,18 @@ namespace React\Promise; -use Countable; -use RuntimeException; - class CallbackWithIntersectionTypehintClass { - #[PHP8] public function __invoke(RuntimeException&Countable $e): void { }/* - public function __invoke(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + #[PHP8] + public static function testCallbackStatic(\RuntimeException&\Countable $e): void {}/* + public static function testCallbackStatic(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ - #[PHP8] public function testCallback(RuntimeException&Countable $e): void { }/* - public function testCallback(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + #[PHP8] + public function testCallback(\RuntimeException&\Countable $e): void {} - #[PHP8] public static function testCallbackStatic(RuntimeException&Countable $e): void { }/* - public static function testCallbackStatic(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + /* + public function testCallback(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + #[PHP8] + public function __invoke(\RuntimeException&\Countable $e): void {}/* + public function __invoke(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ } diff --git a/tests/fixtures/CallbackWithTypehintClass.php b/tests/fixtures/CallbackWithTypehintClass.php index 454eb1c..1958c92 100644 --- a/tests/fixtures/CallbackWithTypehintClass.php +++ b/tests/fixtures/CallbackWithTypehintClass.php @@ -2,19 +2,11 @@ namespace React\Promise; -use InvalidArgumentException; - class CallbackWithTypehintClass { - public function __invoke(InvalidArgumentException $e): void - { - } + public static function testCallbackStatic(\InvalidArgumentException $e): void {} - public function testCallback(InvalidArgumentException $e): void - { - } + public function testCallback(\InvalidArgumentException $e): void {} - public static function testCallbackStatic(InvalidArgumentException $e): void - { - } + public function __invoke(\InvalidArgumentException $e): void {} } diff --git a/tests/fixtures/CallbackWithUnionTypehintClass.php b/tests/fixtures/CallbackWithUnionTypehintClass.php index 61643b8..6bd395c 100644 --- a/tests/fixtures/CallbackWithUnionTypehintClass.php +++ b/tests/fixtures/CallbackWithUnionTypehintClass.php @@ -2,17 +2,18 @@ namespace React\Promise; -use InvalidArgumentException; -use RuntimeException; - class CallbackWithUnionTypehintClass { - #[PHP8] public function __invoke(RuntimeException|InvalidArgumentException $e): void { }/* - public function __invoke(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + #[PHP8] + public static function testCallbackStatic(\RuntimeException|\InvalidArgumentException $e): void {}/* + public static function testCallbackStatic(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ - #[PHP8] public function testCallback(RuntimeException|InvalidArgumentException $e): void { }/* - public function testCallback(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + #[PHP8] + public function testCallback(\RuntimeException|\InvalidArgumentException $e): void {} - #[PHP8] public static function testCallbackStatic(RuntimeException|InvalidArgumentException $e): void { }/* - public static function testCallbackStatic(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + /* + public function testCallback(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + #[PHP8] + public function __invoke(\RuntimeException|\InvalidArgumentException $e): void {}/* + public function __invoke(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ } diff --git a/tests/fixtures/CallbackWithoutTypehintClass.php b/tests/fixtures/CallbackWithoutTypehintClass.php index bdf2542..c197bbe 100644 --- a/tests/fixtures/CallbackWithoutTypehintClass.php +++ b/tests/fixtures/CallbackWithoutTypehintClass.php @@ -4,15 +4,9 @@ class CallbackWithoutTypehintClass { - public function __invoke(): void - { - } + public static function testCallbackStatic(): void {} - public function testCallback(): void - { - } + public function testCallback(): void {} - public static function testCallbackStatic(): void - { - } + public function __invoke(): void {} } diff --git a/tests/fixtures/CountableException.php b/tests/fixtures/CountableException.php index 334cfe2..3b1b5b5 100644 --- a/tests/fixtures/CountableException.php +++ b/tests/fixtures/CountableException.php @@ -2,14 +2,10 @@ namespace React\Promise; -use Countable; -use RuntimeException; - -class CountableException extends RuntimeException implements Countable +class CountableException extends \RuntimeException implements \Countable { public function count(): int { return 0; } } - diff --git a/tests/types/deferred.php b/tests/types/deferred.php index 8f92ca4..1596ded 100644 --- a/tests/types/deferred.php +++ b/tests/types/deferred.php @@ -1,6 +1,7 @@ ', $deferred); // invalid types for arguments of $canceller /** @phpstan-ignore-next-line */ -$deferred = new Deferred(function (int $a, string $b): void { }); +$deferred = new Deferred(function (int $a, string $b): void {}); assertType('React\Promise\Deferred', $deferred); // invalid number of arguments passed to $resolve diff --git a/tests/types/promise.php b/tests/types/promise.php index 4a1afc8..4c73586 100644 --- a/tests/types/promise.php +++ b/tests/types/promise.php @@ -1,6 +1,7 @@ ', $promise); // invalid types for arguments of $resolver /** @phpstan-ignore-next-line */ -$promise = new Promise(function (int $a, string $b): void { }); +$promise = new Promise(function (int $a, string $b): void {}); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $resolve @@ -61,30 +62,30 @@ // invalid number of arguments for $canceller /** @phpstan-ignore-next-line */ -$promise = new Promise(function (): void { }, function ($a, $b, $c): void { }); +$promise = new Promise(function (): void {}, function ($a, $b, $c): void {}); // assertType('React\Promise\PromiseInterface', $promise); // invalid types for arguments of $canceller /** @phpstan-ignore-next-line */ -$promise = new Promise(function (): void { }, function (int $a, string $b): void { }); +$promise = new Promise(function (): void {}, function (int $a, string $b): void {}); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $resolve -$promise = new Promise(function (): void { }, function (callable $resolve): void { +$promise = new Promise(function (): void {}, function (callable $resolve): void { /** @phpstan-ignore-next-line */ $resolve(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $reject -$promise = new Promise(function (): void { }, function (callable $resolve, callable $reject): void { +$promise = new Promise(function (): void {}, function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid type passed to $reject -$promise = new Promise(function(): void { }, function (callable $resolve, callable $reject): void { +$promise = new Promise(function (): void {}, function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(2); }); diff --git a/tests/types/reject.php b/tests/types/reject.php index 42c34ed..2dff255 100644 --- a/tests/types/reject.php +++ b/tests/types/reject.php @@ -1,6 +1,7 @@ ', reject(new RuntimeException())->catch(fn(\UnexpectedValueException $e): int => 42)); assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(fn(): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(function (): void { })); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(function (): void {})); assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(function (): never { throw new \UnexpectedValueException(); })); @@ -32,7 +33,7 @@ assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(fn(\UnexpectedValueException $e): int => 42)); assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(fn(): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(function (): void { })); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(function (): void {})); assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(function (): never { throw new \UnexpectedValueException(); })); diff --git a/tests/types/resolve.php b/tests/types/resolve.php index d034acc..eaf0642 100644 --- a/tests/types/resolve.php +++ b/tests/types/resolve.php @@ -1,6 +1,7 @@ */ -function stringOrIntPromise(): PromiseInterface { +function stringOrIntPromise(): PromiseInterface +{ return resolve(time() % 2 ? 'string' : time()); }; @@ -33,8 +36,8 @@ function stringOrIntPromise(): PromiseInterface { })); assertType('React\Promise\PromiseInterface', resolve(true)->then(null, fn(\Throwable $e): int => 42)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $bool): void { })); -assertType('React\Promise\PromiseInterface', resolve(false)->then(function (bool $bool): void { })->then(function (null $value): void { })); +assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $bool): void {})); +assertType('React\Promise\PromiseInterface', resolve(false)->then(function (bool $bool): void {})->then(function (null $value): void {})); $value = null; assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $v) use (&$value): void { @@ -48,7 +51,7 @@ function stringOrIntPromise(): PromiseInterface { assertType('React\Promise\PromiseInterface', resolve(true)->catch(fn(\Throwable $e): int => 42)); assertType('React\Promise\PromiseInterface', resolve(true)->catch(fn(\Throwable $e): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): void { })); +assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): void {})); // assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): never { // throw new \RuntimeException(); // })); @@ -62,7 +65,7 @@ function stringOrIntPromise(): PromiseInterface { assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(fn(\Throwable $e): int => 42)); assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(fn(\Throwable $e): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): void { })); +assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): void {})); // assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): never { // throw new \RuntimeException(); // })); From 992d13cd01a37fb8c9be392058c4f326490bbf0e Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 16:48:39 +0400 Subject: [PATCH 10/18] style: Apply risky Code Style rules to tests --- tests/DeferredTest.php | 26 ++--- tests/Fiber.php | 6 +- tests/FunctionAllTest.php | 8 +- tests/FunctionAnyTest.php | 16 +-- tests/FunctionCheckTypehintTest.php | 8 +- tests/FunctionRaceTest.php | 14 +-- tests/FunctionRejectTest.php | 2 + tests/FunctionResolveTest.php | 12 ++- tests/Internal/CancellationQueueTest.php | 2 + tests/Internal/FulfilledPromiseTest.php | 10 +- tests/Internal/RejectedPromiseTest.php | 10 +- tests/PHP8.php | 4 +- .../PromiseAdapter/CallbackPromiseAdapter.php | 10 +- .../PromiseAdapterInterface.php | 2 + tests/PromiseTest.php | 98 ++++++++++--------- tests/PromiseTest/CancelTestTrait.php | 30 +++--- tests/PromiseTest/FullTestTrait.php | 2 + .../PromiseTest/PromiseFulfilledTestTrait.php | 32 +++--- tests/PromiseTest/PromisePendingTestTrait.php | 6 +- .../PromiseTest/PromiseRejectedTestTrait.php | 42 ++++---- tests/PromiseTest/PromiseSettledTestTrait.php | 6 +- tests/PromiseTest/RejectTestTrait.php | 14 +-- tests/PromiseTest/ResolveTestTrait.php | 14 +-- tests/TestCase.php | 12 ++- .../CallbackWithIntersectionTypehintClass.php | 2 + tests/fixtures/CallbackWithTypehintClass.php | 2 + .../CallbackWithUnionTypehintClass.php | 2 + .../fixtures/CallbackWithoutTypehintClass.php | 2 + tests/fixtures/CountableException.php | 2 + tests/fixtures/IterableException.php | 2 + .../fixtures/SimpleFulfilledTestThenable.php | 2 + tests/fixtures/SimpleTestCancellable.php | 2 + .../SimpleTestCancellableThenable.php | 4 +- tests/types/all.php | 6 +- tests/types/any.php | 6 +- tests/types/deferred.php | 10 +- tests/types/promise.php | 24 ++--- tests/types/race.php | 6 +- tests/types/reject.php | 30 +++--- tests/types/resolve.php | 36 +++---- 40 files changed, 302 insertions(+), 222 deletions(-) diff --git a/tests/DeferredTest.php b/tests/DeferredTest.php index b68d53f..0af86cd 100644 --- a/tests/DeferredTest.php +++ b/tests/DeferredTest.php @@ -1,5 +1,7 @@ promise()->cancel(); unset($deferred); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -46,16 +48,16 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithEx */ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException(): void { - gc_collect_cycles(); - gc_collect_cycles(); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on + \gc_collect_cycles(); + \gc_collect_cycles(); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on - $deferred = new Deferred(function ($resolve, $reject): void { + $deferred = new Deferred(static function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $deferred->promise()->then()->cancel(); unset($deferred); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -63,12 +65,12 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejects */ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenceAndExplicitlyRejectWithException(): void { - gc_collect_cycles(); - gc_collect_cycles(); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on + \gc_collect_cycles(); + \gc_collect_cycles(); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on /** @var Deferred $deferred */ - $deferred = new Deferred(function () use (&$deferred): void { - assert($deferred instanceof Deferred); + $deferred = new Deferred(static function () use (&$deferred): void { + \assert($deferred instanceof Deferred); }); $deferred->promise()->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection @@ -76,6 +78,6 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenc $deferred->reject(new \Exception('foo')); unset($deferred); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } } diff --git a/tests/Fiber.php b/tests/Fiber.php index cca384d..0e92bc0 100644 --- a/tests/Fiber.php +++ b/tests/Fiber.php @@ -1,6 +1,8 @@ method('__invoke') ->with(self::identicalTo([1, 2, 3])); - $gen = (function () { + $gen = (static function () { for ($i = 1; $i <= 3; ++$i) { yield $i; } @@ -95,7 +97,7 @@ public function shouldResolveValuesGeneratorEmpty(): void ->method('__invoke') ->with(self::identicalTo([])); - $gen = (function () { + $gen = (static function () { if (false) { // @phpstan-ignore-line yield; } @@ -133,7 +135,7 @@ public function shouldRejectInfiteGeneratorOrRejectedPromises(): void ->method('__invoke') ->with(new \RuntimeException('Iteration 1')); - $gen = (function () { + $gen = (static function () { for ($i = 1; ; ++$i) { yield reject(new \RuntimeException('Iteration ' . $i)); } diff --git a/tests/FunctionAnyTest.php b/tests/FunctionAnyTest.php index f7393e2..15bfc46 100644 --- a/tests/FunctionAnyTest.php +++ b/tests/FunctionAnyTest.php @@ -1,5 +1,7 @@ expects(self::once()) ->method('__invoke') ->with( - self::callback(fn($exception) => $exception instanceof LengthException && + self::callback(static fn($exception) => $exception instanceof LengthException && $exception->getMessage() === 'Must contain at least 1 item but contains only 0 items.'), ); @@ -36,7 +38,7 @@ public function shouldRejectWithLengthExceptionWithEmptyInputGenerator(): void ->method('__invoke') ->with(new LengthException('Must contain at least 1 item but contains only 0 items.')); - $gen = (function () { + $gen = (static function () { if (false) { // @phpstan-ignore-line yield; } @@ -104,7 +106,7 @@ public function shouldResolveValuesGenerator(): void ->method('__invoke') ->with(self::identicalTo(1)); - $gen = (function () { + $gen = (static function () { for ($i = 1; $i <= 3; ++$i) { yield $i; } @@ -124,7 +126,7 @@ public function shouldResolveValuesInfiniteGenerator(): void ->method('__invoke') ->with(self::identicalTo(1)); - $gen = (function () { + $gen = (static function () { for ($i = 1; ; ++$i) { yield $i; } @@ -226,8 +228,8 @@ public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue */ public function shouldCancelInputArrayPromises(): void { - $promise1 = new Promise(function (): void {}, $this->expectCallableOnce()); - $promise2 = new Promise(function (): void {}, $this->expectCallableOnce()); + $promise1 = new Promise(static function (): void {}, $this->expectCallableOnce()); + $promise2 = new Promise(static function (): void {}, $this->expectCallableOnce()); any([$promise1, $promise2])->cancel(); } @@ -240,7 +242,7 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfill $deferred = new Deferred($this->expectCallableNever()); $deferred->resolve(null); - $promise2 = new Promise(function (): void {}, $this->expectCallableNever()); + $promise2 = new Promise(static function (): void {}, $this->expectCallableNever()); any([$deferred->promise(), $promise2])->cancel(); } diff --git a/tests/FunctionCheckTypehintTest.php b/tests/FunctionCheckTypehintTest.php index c41d467..52c2df2 100644 --- a/tests/FunctionCheckTypehintTest.php +++ b/tests/FunctionCheckTypehintTest.php @@ -1,5 +1,7 @@ method('__invoke') ->with(self::identicalTo(1)); - $gen = (function () { + $gen = (static function () { for ($i = 1; $i <= 3; ++$i) { yield $i; } @@ -102,7 +104,7 @@ public function shouldResolveValuesInfiniteGenerator(): void ->method('__invoke') ->with(self::identicalTo(1)); - $gen = (function () { + $gen = (static function () { for ($i = 1; ; ++$i) { yield $i; } @@ -143,8 +145,8 @@ public function shouldRejectIfFirstSettledPromiseRejects(): void */ public function shouldCancelInputArrayPromises(): void { - $promise1 = new Promise(function (): void {}, $this->expectCallableOnce()); - $promise2 = new Promise(function (): void {}, $this->expectCallableOnce()); + $promise1 = new Promise(static function (): void {}, $this->expectCallableOnce()); + $promise2 = new Promise(static function (): void {}, $this->expectCallableOnce()); race([$promise1, $promise2])->cancel(); } @@ -157,7 +159,7 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfill $deferred = new Deferred($this->expectCallableNever()); $deferred->resolve(null); - $promise2 = new Promise(function (): void {}, $this->expectCallableNever()); + $promise2 = new Promise(static function (): void {}, $this->expectCallableNever()); race([$deferred->promise(), $promise2])->cancel(); } @@ -170,7 +172,7 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseRejects $deferred = new Deferred($this->expectCallableNever()); $deferred->reject(new \Exception()); - $promise2 = new Promise(function (): void {}, $this->expectCallableNever()); + $promise2 = new Promise(static function (): void {}, $this->expectCallableNever()); race([$deferred->promise(), $promise2])->cancel(); } diff --git a/tests/FunctionRejectTest.php b/tests/FunctionRejectTest.php index 9c3be23..8125b22 100644 --- a/tests/FunctionRejectTest.php +++ b/tests/FunctionRejectTest.php @@ -1,5 +1,7 @@ resolve(false); - $result = resolve(resolve($d->promise()->then(function ($val) { + $result = resolve(resolve($d->promise()->then(static function ($val) { $d = new Deferred(); $d->resolve($val); - $identity = fn($val) => $val; + $identity = static fn($val) => $val; return resolve($d->promise()->then($identity))->then( - fn($val) => !$val, + static fn($val) => !$val, ); }))); @@ -137,7 +139,7 @@ public function shouldSupportDeepNestingInPromiseChains(): void */ public function shouldSupportVeryDeepNestedPromises(): void { - if (PHP_VERSION_ID < 70200 && ini_get('xdebug.max_nesting_level') !== false) { + if (PHP_VERSION_ID < 70200 && \ini_get('xdebug.max_nesting_level') !== false) { $this->markTestSkipped('Skip unhandled rejection on legacy PHP 7.1'); } @@ -149,7 +151,7 @@ public function shouldSupportVeryDeepNestedPromises(): void $last = $p; for ($j = 0; $j < 150; $j++) { - $last = $last->then(fn($result) => $result); + $last = $last->then(static fn($result) => $result); } } diff --git a/tests/Internal/CancellationQueueTest.php b/tests/Internal/CancellationQueueTest.php index 694248a..e4ca3ea 100644 --- a/tests/Internal/CancellationQueueTest.php +++ b/tests/Internal/CancellationQueueTest.php @@ -1,5 +1,7 @@ function () use (&$promise) { + 'promise' => static function () use (&$promise) { if (!$promise) { throw new \LogicException('FulfilledPromise must be resolved before obtaining the promise'); } return $promise; }, - 'resolve' => function ($value = null) use (&$promise): void { + 'resolve' => static function ($value = null) use (&$promise): void { if (!$promise) { $promise = new FulfilledPromise($value); } }, - 'reject' => function (): void { + 'reject' => static function (): void { throw new \LogicException('You cannot call reject() for React\Promise\FulfilledPromise'); }, - 'settle' => function ($value = null) use (&$promise): void { + 'settle' => static function ($value = null) use (&$promise): void { if (!$promise) { $promise = new FulfilledPromise($value); } diff --git a/tests/Internal/RejectedPromiseTest.php b/tests/Internal/RejectedPromiseTest.php index 0aa5573..f875936 100644 --- a/tests/Internal/RejectedPromiseTest.php +++ b/tests/Internal/RejectedPromiseTest.php @@ -1,5 +1,7 @@ function () use (&$promise) { + 'promise' => static function () use (&$promise) { if (!$promise) { throw new \LogicException('RejectedPromise must be rejected before obtaining the promise'); } return $promise; }, - 'resolve' => function (): void { + 'resolve' => static function (): void { throw new \LogicException('You cannot call resolve() for React\Promise\RejectedPromise'); }, - 'reject' => function (\Throwable $reason) use (&$promise): void { + 'reject' => static function (\Throwable $reason) use (&$promise): void { if (!$promise) { $promise = new RejectedPromise($reason); } }, - 'settle' => function ($reason = '') use (&$promise): void { + 'settle' => static function ($reason = '') use (&$promise): void { if (!$promise) { if (!$reason instanceof \Exception) { $reason = new \Exception((string) $reason); diff --git a/tests/PHP8.php b/tests/PHP8.php index 4e2b7d4..b6f00ef 100644 --- a/tests/PHP8.php +++ b/tests/PHP8.php @@ -1,5 +1,7 @@ = 80000); + \assert(\PHP_VERSION_ID >= 80000); } } diff --git a/tests/PromiseAdapter/CallbackPromiseAdapter.php b/tests/PromiseAdapter/CallbackPromiseAdapter.php index 421d7f5..1298098 100644 --- a/tests/PromiseAdapter/CallbackPromiseAdapter.php +++ b/tests/PromiseAdapter/CallbackPromiseAdapter.php @@ -1,5 +1,7 @@ callbacks['promise'])(...func_get_args()); + return ($this->callbacks['promise'])(...\func_get_args()); } public function resolve($value): void { - ($this->callbacks['resolve'])(...func_get_args()); + ($this->callbacks['resolve'])(...\func_get_args()); } public function reject(): void { - ($this->callbacks['reject'])(...func_get_args()); + ($this->callbacks['reject'])(...\func_get_args()); } public function settle(): void { - ($this->callbacks['settle'])(...func_get_args()); + ($this->callbacks['settle'])(...\func_get_args()); } } diff --git a/tests/PromiseAdapter/PromiseAdapterInterface.php b/tests/PromiseAdapter/PromiseAdapterInterface.php index 82023b7..e050e3f 100644 --- a/tests/PromiseAdapter/PromiseAdapterInterface.php +++ b/tests/PromiseAdapter/PromiseAdapterInterface.php @@ -1,5 +1,7 @@ fn() => $promise, + 'promise' => static fn() => $promise, 'resolve' => $resolveCallback, 'reject' => $rejectCallback, 'settle' => $resolveCallback, @@ -41,7 +43,7 @@ public function shouldRejectIfResolverThrowsException(): void { $exception = new \Exception('foo'); - $promise = new Promise(function () use ($exception): void { + $promise = new Promise(static function () use ($exception): void { throw $exception; }); @@ -60,13 +62,13 @@ public function shouldRejectIfResolverThrowsException(): void */ public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithException(): void { - gc_collect_cycles(); - $promise = new Promise(function ($resolve): void { + \gc_collect_cycles(); + $promise = new Promise(static function ($resolve): void { $resolve(new \Exception('foo')); }); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -74,8 +76,8 @@ public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithE */ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptionWithoutResolver(): void { - gc_collect_cycles(); - $promise = new Promise(function (): void { + \gc_collect_cycles(); + $promise = new Promise(static function (): void { throw new \Exception('foo'); }); @@ -83,7 +85,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -91,8 +93,8 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio */ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithException(): void { - gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject): void { + \gc_collect_cycles(); + $promise = new Promise(static function ($resolve, $reject): void { $reject(new \Exception('foo')); }); @@ -100,7 +102,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithExc unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -108,14 +110,14 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithExc */ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException(): void { - gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject): void {}, function ($resolve, $reject): void { + \gc_collect_cycles(); + $promise = new Promise(static function ($resolve, $reject): void {}, static function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $promise->cancel(); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -123,14 +125,14 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithEx */ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException(): void { - gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject): void {}, function ($resolve, $reject): void { + \gc_collect_cycles(); + $promise = new Promise(static function ($resolve, $reject): void {}, static function ($resolve, $reject): void { $reject(new \Exception('foo')); }); $promise->then()->then()->then()->cancel(); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -138,8 +140,8 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejects */ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsException(): void { - gc_collect_cycles(); - $promise = new Promise(function ($resolve, $reject): void { + \gc_collect_cycles(); + $promise = new Promise(static function ($resolve, $reject): void { throw new \Exception('foo'); }); @@ -147,7 +149,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -155,11 +157,11 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise(): void { - gc_collect_cycles(); - $promise = new Promise(function (): void {}); + \gc_collect_cycles(); + $promise = new Promise(static function (): void {}); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -167,12 +169,12 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithThenFollowers(): void { - gc_collect_cycles(); - $promise = new Promise(function (): void {}); + \gc_collect_cycles(); + $promise = new Promise(static function (): void {}); $promise->then()->then()->then(); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -180,12 +182,12 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithCatchFollowers(): void { - gc_collect_cycles(); - $promise = new Promise(function (): void {}); - $promise->catch(function (): void {}); + \gc_collect_cycles(); + $promise = new Promise(static function (): void {}); + $promise->catch(static function (): void {}); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -193,12 +195,12 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithFinallyFollowers(): void { - gc_collect_cycles(); - $promise = new Promise(function (): void {}); - $promise->finally(function (): void {}); + \gc_collect_cycles(); + $promise = new Promise(static function (): void {}); + $promise->finally(static function (): void {}); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -207,12 +209,12 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithOtherwiseFollowers(): void { - gc_collect_cycles(); - $promise = new Promise(function (): void {}); - $promise->otherwise(function (): void {}); + \gc_collect_cycles(); + $promise = new Promise(static function (): void {}); + $promise->otherwise(static function (): void {}); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -221,12 +223,12 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithAlwaysFollowers(): void { - gc_collect_cycles(); - $promise = new Promise(function (): void {}); - $promise->always(function (): void {}); + \gc_collect_cycles(); + $promise = new Promise(static function (): void {}); + $promise->always(static function (): void {}); unset($promise); - $this->assertSame(0, gc_collect_cycles()); + $this->assertSame(0, \gc_collect_cycles()); } /** @@ -234,8 +236,8 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro */ public function shouldFulfillIfFullfilledWithSimplePromise(): void { - gc_collect_cycles(); - $promise = new Promise(function (): void { + \gc_collect_cycles(); + $promise = new Promise(static function (): void { throw new \Exception('foo'); }); @@ -243,6 +245,6 @@ public function shouldFulfillIfFullfilledWithSimplePromise(): void unset($promise); - self::assertSame(0, gc_collect_cycles()); + self::assertSame(0, \gc_collect_cycles()); } } diff --git a/tests/PromiseTest/CancelTestTrait.php b/tests/PromiseTest/CancelTestTrait.php index fe0a8c6..ac8e44e 100644 --- a/tests/PromiseTest/CancelTestTrait.php +++ b/tests/PromiseTest/CancelTestTrait.php @@ -1,5 +1,7 @@ getPromiseTestAdapter(function ($resolve, $reject) use (&$args): void { - $args = func_get_args(); + $adapter = $this->getPromiseTestAdapter(static function ($resolve, $reject) use (&$args): void { + $args = \func_get_args(); }); $adapter->promise()->cancel(); self::assertCount(2, $args); - self::assertTrue(is_callable($args[0])); - self::assertTrue(is_callable($args[1])); + self::assertTrue(\is_callable($args[0])); + self::assertTrue(\is_callable($args[1])); } /** @@ -32,8 +34,8 @@ public function cancelShouldCallCancellerWithResolverArguments(): void public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed(): void { $args = null; - $adapter = $this->getPromiseTestAdapter(function () use (&$args): void { - $args = func_num_args(); + $adapter = $this->getPromiseTestAdapter(static function () use (&$args): void { + $args = \func_num_args(); }); $adapter->promise()->cancel(); @@ -46,7 +48,7 @@ public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed(): void */ public function cancelShouldFulfillPromiseIfCancellerFulfills(): void { - $adapter = $this->getPromiseTestAdapter(function ($resolve): void { + $adapter = $this->getPromiseTestAdapter(static function ($resolve): void { $resolve(1); }); @@ -69,7 +71,7 @@ public function cancelShouldRejectPromiseIfCancellerRejects(): void { $exception = new \Exception(); - $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject) use ($exception): void { + $adapter = $this->getPromiseTestAdapter(static function ($resolve, $reject) use ($exception): void { $reject($exception); }); @@ -92,7 +94,7 @@ public function cancelShouldRejectPromiseWithExceptionIfCancellerThrows(): void { $e = new \Exception(); - $adapter = $this->getPromiseTestAdapter(function () use ($e): void { + $adapter = $this->getPromiseTestAdapter(static function () use ($e): void { throw $e; }); @@ -117,7 +119,7 @@ public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves(): void $mock ->expects($this->once()) ->method('__invoke') - ->will($this->returnCallback(function ($resolve): void { + ->will($this->returnCallback(static function ($resolve): void { $resolve(null); })); @@ -132,7 +134,7 @@ public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves(): void */ public function cancelShouldHaveNoEffectIfCancellerDoesNothing(): void { - $adapter = $this->getPromiseTestAdapter(function (): void {}); + $adapter = $this->getPromiseTestAdapter(static function (): void {}); $adapter->promise() ->then($this->expectCallableNever(), $this->expectCallableNever()); @@ -149,13 +151,13 @@ public function cancelShouldCallCancellerFromDeepNestedPromiseChain(): void $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); $promise = $adapter->promise() - ->then(fn() => new Promise\Promise(function (): void {})) - ->then(function () { + ->then(static fn() => new Promise\Promise(static function (): void {})) + ->then(static function () { $d = new Promise\Deferred(); return $d->promise(); }) - ->then(fn() => new Promise\Promise(function (): void {})); + ->then(static fn() => new Promise\Promise(static function (): void {})); $promise->cancel(); } diff --git a/tests/PromiseTest/FullTestTrait.php b/tests/PromiseTest/FullTestTrait.php index e0ffc23..e34ba4a 100644 --- a/tests/PromiseTest/FullTestTrait.php +++ b/tests/PromiseTest/FullTestTrait.php @@ -1,5 +1,7 @@ resolve(1); $adapter->promise() ->then( - fn($val) => $val + 1, + static fn($val) => $val + 1, $this->expectCallableNever(), ) ->then( @@ -120,7 +122,7 @@ public function thenShouldForwardPromisedCallbackResultValueToNextCallback(): vo $adapter->resolve(1); $adapter->promise() ->then( - fn($val) => resolve($val + 1), + static fn($val) => resolve($val + 1), $this->expectCallableNever(), ) ->then( @@ -147,7 +149,7 @@ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackReturnsARejec $adapter->resolve(1); $adapter->promise() ->then( - fn() => reject($exception), + static fn() => reject($exception), $this->expectCallableNever(), ) ->then( @@ -199,8 +201,8 @@ public function thenShouldContinueToExecuteCallbacksWhenPriorCallbackSuspendsFib $adapter = $this->getPromiseTestAdapter(); $adapter->resolve(42); - $fiber = new \Fiber(function () use ($adapter): void { - $adapter->promise()->then(function (int $value): void { + $fiber = new \Fiber(static function () use ($adapter): void { + $adapter->promise()->then(static function (int $value): void { \Fiber::suspend($value); }); }); @@ -257,7 +259,7 @@ public function finallyShouldNotSuppressValueForFulfilledPromise(): void $adapter->resolve($value); $adapter->promise() - ->finally(function (): void {}) + ->finally(static function (): void {}) ->then($mock); } @@ -279,7 +281,7 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFul $adapter->resolve($value); $adapter->promise() // @phpstan-ignore-line - ->finally(fn(): int => 1) + ->finally(static fn(): int => 1) ->then($mock); } @@ -301,7 +303,7 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfil $adapter->resolve($value); $adapter->promise() // @phpstan-ignore-line - ->finally(fn(): PromiseInterface => resolve(1)) + ->finally(static fn(): PromiseInterface => resolve(1)) ->then($mock); } @@ -322,7 +324,7 @@ public function finallyShouldRejectWhenHandlerThrowsForFulfilledPromise(): void $adapter->resolve(1); $adapter->promise() - ->finally(function () use ($exception): void { + ->finally(static function () use ($exception): void { throw $exception; }) ->then(null, $mock); @@ -345,7 +347,7 @@ public function finallyShouldRejectWhenHandlerRejectsForFulfilledPromise(): void $adapter->resolve(1); $adapter->promise() - ->finally(fn() => reject($exception)) + ->finally(static fn() => reject($exception)) ->then(null, $mock); } @@ -379,7 +381,7 @@ public function alwaysShouldNotSuppressValueForFulfilledPromise(): void $adapter->resolve($value); $adapter->promise() - ->always(function (): void {}) + ->always(static function (): void {}) ->then($mock); } @@ -402,7 +404,7 @@ public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulf $adapter->resolve($value); $adapter->promise() // @phpstan-ignore-line - ->always(fn(): int => 1) + ->always(static fn(): int => 1) ->then($mock); } @@ -425,7 +427,7 @@ public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfill $adapter->resolve($value); $adapter->promise() // @phpstan-ignore-line - ->always(fn(): PromiseInterface => resolve(1)) + ->always(static fn(): PromiseInterface => resolve(1)) ->then($mock); } @@ -447,7 +449,7 @@ public function alwaysShouldRejectWhenHandlerThrowsForFulfilledPromise(): void $adapter->resolve(1); $adapter->promise() - ->always(function () use ($exception): void { + ->always(static function () use ($exception): void { throw $exception; }) ->then(null, $mock); @@ -471,7 +473,7 @@ public function alwaysShouldRejectWhenHandlerRejectsForFulfilledPromise(): void $adapter->resolve(1); $adapter->promise() - ->always(fn() => reject($exception)) + ->always(static fn() => reject($exception)) ->then(null, $mock); } } diff --git a/tests/PromiseTest/PromisePendingTestTrait.php b/tests/PromiseTest/PromisePendingTestTrait.php index befd319..170ddf0 100644 --- a/tests/PromiseTest/PromisePendingTestTrait.php +++ b/tests/PromiseTest/PromisePendingTestTrait.php @@ -1,5 +1,7 @@ getPromiseTestAdapter(); - self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->finally(function (): void {})); + self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->finally(static function (): void {})); } /** @@ -70,6 +72,6 @@ public function alwaysShouldReturnAPromiseForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); - self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->always(function (): void {})); + self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->always(static function (): void {})); } } diff --git a/tests/PromiseTest/PromiseRejectedTestTrait.php b/tests/PromiseTest/PromiseRejectedTestTrait.php index 7cfc20d..afbcf2b 100644 --- a/tests/PromiseTest/PromiseRejectedTestTrait.php +++ b/tests/PromiseTest/PromiseRejectedTestTrait.php @@ -1,5 +1,7 @@ promise() ->then( $this->expectCallableNever(), - function (): void { + static function (): void { // Presence of rejection handler is enough to switch back // to resolve mode, even though it returns undefined. // The ONLY way to propagate a rejection is to re-throw or @@ -106,7 +108,7 @@ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackDoesNotExplicitlyP $adapter->promise() ->then( $this->expectCallableNever(), - fn() => 2, + static fn() => 2, ) ->then( $mock, @@ -131,7 +133,7 @@ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackReturnsAResolution $adapter->promise() ->then( $this->expectCallableNever(), - fn() => resolve(2), + static fn() => resolve(2), ) ->then( $mock, @@ -191,7 +193,7 @@ public function shouldPropagateRejectionsWhenErrbackReturnsARejection(): void $adapter->promise() ->then( $this->expectCallableNever(), - fn() => reject($exception), + static fn() => reject($exception), ) ->then( $this->expectCallableNever(), @@ -235,7 +237,7 @@ public function catchShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExcept $adapter->reject($exception); $adapter->promise() - ->catch(function ($reason) use ($mock): void { + ->catch(static function ($reason) use ($mock): void { $mock($reason); }); } @@ -257,7 +259,7 @@ public function catchShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejec $adapter->reject($exception); $adapter->promise() - ->catch(function (\InvalidArgumentException $reason) use ($mock): void { + ->catch(static function (\InvalidArgumentException $reason) use ($mock): void { $mock($reason); }); } @@ -275,7 +277,7 @@ public function catchShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchTypehint $adapter->reject($exception); $adapter->promise() - ->catch(function (\InvalidArgumentException $reason) use ($mock): void { + ->catch(static function (\InvalidArgumentException $reason) use ($mock): void { $mock($reason); })->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection } @@ -297,7 +299,7 @@ public function finallyShouldNotSuppressRejectionForRejectedPromise(): void $adapter->reject($exception); $adapter->promise() - ->finally(function (): void {}) + ->finally(static function (): void {}) ->then(null, $mock); } @@ -318,7 +320,7 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseFo $adapter->reject($exception); $adapter->promise() - ->finally(fn(): int => + ->finally(static fn(): int => // @phpstan-ignore-line 1) ->then(null, $mock); @@ -341,7 +343,7 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRe $adapter->reject($exception); $adapter->promise() - ->finally(fn(): PromiseInterface => + ->finally(static fn(): PromiseInterface => // @phpstan-ignore-line resolve(1)) ->then(null, $mock); @@ -365,7 +367,7 @@ public function finallyShouldRejectWhenHandlerThrowsForRejectedPromise(): void $adapter->reject($exception1); $adapter->promise() - ->finally(function () use ($exception2): void { + ->finally(static function () use ($exception2): void { throw $exception2; }) ->then(null, $mock); @@ -389,7 +391,7 @@ public function finallyShouldRejectWhenHandlerRejectsForRejectedPromise(): void $adapter->reject($exception1); $adapter->promise() - ->finally(fn() => reject($exception2)) + ->finally(static fn() => reject($exception2)) ->then(null, $mock); } @@ -443,7 +445,7 @@ public function otherwiseShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnEx $adapter->reject($exception); $adapter->promise() - ->otherwise(function ($reason) use ($mock): void { + ->otherwise(static function ($reason) use ($mock): void { $mock($reason); }); } @@ -466,7 +468,7 @@ public function otherwiseShouldInvokeRejectionHandlerIfReasonMatchesTypehintForR $adapter->reject($exception); $adapter->promise() - ->otherwise(function (\InvalidArgumentException $reason) use ($mock): void { + ->otherwise(static function (\InvalidArgumentException $reason) use ($mock): void { $mock($reason); }); } @@ -485,7 +487,7 @@ public function otherwiseShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchType $adapter->reject($exception); $adapter->promise() - ->otherwise(function (\InvalidArgumentException $reason) use ($mock): void { + ->otherwise(static function (\InvalidArgumentException $reason) use ($mock): void { $mock($reason); })->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection } @@ -508,7 +510,7 @@ public function alwaysShouldNotSuppressRejectionForRejectedPromise(): void $adapter->reject($exception); $adapter->promise() - ->always(function (): void {}) + ->always(static function (): void {}) ->then(null, $mock); } @@ -530,7 +532,7 @@ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseFor $adapter->reject($exception); $adapter->promise() - ->finally(fn(): int => + ->finally(static fn(): int => // @phpstan-ignore-line 1) ->then(null, $mock); @@ -554,7 +556,7 @@ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRej $adapter->reject($exception); $adapter->promise() - ->always(fn(): PromiseInterface => + ->always(static fn(): PromiseInterface => // @phpstan-ignore-line resolve(1)) ->then(null, $mock); @@ -579,7 +581,7 @@ public function alwaysShouldRejectWhenHandlerThrowsForRejectedPromise(): void $adapter->reject($exception1); $adapter->promise() - ->always(function () use ($exception2): void { + ->always(static function () use ($exception2): void { throw $exception2; }) ->then(null, $mock); @@ -604,7 +606,7 @@ public function alwaysShouldRejectWhenHandlerRejectsForRejectedPromise(): void $adapter->reject($exception1); $adapter->promise() - ->always(fn() => reject($exception2)) + ->always(static fn() => reject($exception2)) ->then(null, $mock); } } diff --git a/tests/PromiseTest/PromiseSettledTestTrait.php b/tests/PromiseTest/PromiseSettledTestTrait.php index 3a33bdc..9b4e5a8 100644 --- a/tests/PromiseTest/PromiseSettledTestTrait.php +++ b/tests/PromiseTest/PromiseSettledTestTrait.php @@ -1,5 +1,7 @@ getPromiseTestAdapter(); $adapter->settle(null); - self::assertInstanceOf(PromiseInterface::class, $promise = $adapter->promise()->finally(function (): void {})); + self::assertInstanceOf(PromiseInterface::class, $promise = $adapter->promise()->finally(static function (): void {})); if ($promise instanceof RejectedPromise) { $promise->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection @@ -76,7 +78,7 @@ public function alwaysShouldReturnAPromiseForSettledPromise(): void $adapter = $this->getPromiseTestAdapter(); $adapter->settle(null); - self::assertInstanceOf(PromiseInterface::class, $promise = $adapter->promise()->always(function (): void {})); + self::assertInstanceOf(PromiseInterface::class, $promise = $adapter->promise()->always(static function (): void {})); if ($promise instanceof RejectedPromise) { $promise->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection diff --git a/tests/PromiseTest/RejectTestTrait.php b/tests/PromiseTest/RejectTestTrait.php index 3e08e91..044f0fb 100644 --- a/tests/PromiseTest/RejectTestTrait.php +++ b/tests/PromiseTest/RejectTestTrait.php @@ -1,5 +1,7 @@ with($this->identicalTo($exception1)); $adapter->promise() - ->then(null, function (\Throwable $value) use ($exception3, $adapter): PromiseInterface { + ->then(null, static function (\Throwable $value) use ($exception3, $adapter): PromiseInterface { $adapter->reject($exception3); return reject($value); @@ -129,7 +131,7 @@ public function finallyShouldNotSuppressRejection(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function (): void {}) + ->finally(static function (): void {}) ->then(null, $mock); $adapter->reject($exception); @@ -152,7 +154,7 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromise() $adapter->promise() // @phpstan-ignore-line - ->finally(fn(): int => 1) + ->finally(static fn(): int => 1) ->then(null, $mock); $adapter->reject($exception); @@ -175,7 +177,7 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromise(): v $adapter->promise() // @phpstan-ignore-line - ->finally(fn(): PromiseInterface => resolve(1)) + ->finally(static fn(): PromiseInterface => resolve(1)) ->then(null, $mock); $adapter->reject($exception); @@ -197,7 +199,7 @@ public function finallyShouldRejectWhenHandlerThrowsForRejection(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function () use ($exception): void { + ->finally(static function () use ($exception): void { throw $exception; }) ->then(null, $mock); @@ -221,7 +223,7 @@ public function finallyShouldRejectWhenHandlerRejectsForRejection(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(fn() => reject($exception)) + ->finally(static fn() => reject($exception)) ->then(null, $mock); $adapter->reject($exception); diff --git a/tests/PromiseTest/ResolveTestTrait.php b/tests/PromiseTest/ResolveTestTrait.php index 66e0ab6..d1bcb8b 100644 --- a/tests/PromiseTest/ResolveTestTrait.php +++ b/tests/PromiseTest/ResolveTestTrait.php @@ -1,5 +1,7 @@ with($this->identicalTo(1)); $adapter->promise() - ->then(function ($value) use ($adapter) { + ->then(static function ($value) use ($adapter) { $adapter->resolve(3); return $value; @@ -190,7 +192,7 @@ public function finallyShouldNotSuppressValue(): void ->with($this->identicalTo($value)); $adapter->promise() - ->finally(function (): void {}) + ->finally(static function (): void {}) ->then($mock); $adapter->resolve($value); @@ -213,7 +215,7 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromise(): vo $adapter->promise() // @phpstan-ignore-line - ->finally(fn(): int => 1) + ->finally(static fn(): int => 1) ->then($mock); $adapter->resolve($value); @@ -236,7 +238,7 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromise(): void $adapter->promise() // @phpstan-ignore-line - ->finally(fn(): PromiseInterface => + ->finally(static fn(): PromiseInterface => resolve(1)) ->then($mock); @@ -259,7 +261,7 @@ public function finallyShouldRejectWhenHandlerThrowsForFulfillment(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(function () use ($exception): void { + ->finally(static function () use ($exception): void { throw $exception; }) ->then(null, $mock); @@ -283,7 +285,7 @@ public function finallyShouldRejectWhenHandlerRejectsForFulfillment(): void ->with($this->identicalTo($exception)); $adapter->promise() - ->finally(fn() => reject($exception)) + ->finally(static fn() => reject($exception)) ->then(null, $mock); $adapter->resolve(1); diff --git a/tests/TestCase.php b/tests/TestCase.php index c01a4a8..5b3c0fa 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,5 +1,7 @@ createCallableMock(); $mock->expects(self::exactly($amount))->method('__invoke'); - assert(is_callable($mock)); + \assert(\is_callable($mock)); return $mock; } @@ -20,7 +22,7 @@ public function expectCallableOnce(): callable { $mock = $this->createCallableMock(); $mock->expects(self::once())->method('__invoke'); - assert(is_callable($mock)); + \assert(\is_callable($mock)); return $mock; } @@ -29,7 +31,7 @@ public function expectCallableNever(): callable { $mock = $this->createCallableMock(); $mock->expects(self::never())->method('__invoke'); - assert(is_callable($mock)); + \assert(\is_callable($mock)); return $mock; } @@ -40,14 +42,14 @@ public function expectCallableNever(): callable protected function createCallableMock(): MockObject { $builder = $this->getMockBuilder(\stdClass::class); - if (method_exists($builder, 'addMethods')) { + if (\method_exists($builder, 'addMethods')) { // PHPUnit 9+ $mock = $builder->addMethods(['__invoke'])->getMock(); } else { // legacy PHPUnit 4 - PHPUnit 9 $mock = $builder->setMethods(['__invoke'])->getMock(); } - assert($mock instanceof MockObject && is_callable($mock)); + \assert($mock instanceof MockObject && \is_callable($mock)); return $mock; } diff --git a/tests/fixtures/CallbackWithIntersectionTypehintClass.php b/tests/fixtures/CallbackWithIntersectionTypehintClass.php index 8228f27..33e6b37 100644 --- a/tests/fixtures/CallbackWithIntersectionTypehintClass.php +++ b/tests/fixtures/CallbackWithIntersectionTypehintClass.php @@ -1,5 +1,7 @@ */ diff --git a/tests/fixtures/SimpleFulfilledTestThenable.php b/tests/fixtures/SimpleFulfilledTestThenable.php index c435bcc..59c1c2f 100644 --- a/tests/fixtures/SimpleFulfilledTestThenable.php +++ b/tests/fixtures/SimpleFulfilledTestThenable.php @@ -1,5 +1,7 @@ cancelCalled = true; - if (is_callable($this->onCancel)) { + if (\is_callable($this->onCancel)) { ($this->onCancel)(); } } diff --git a/tests/types/all.php b/tests/types/all.php index b02b9f1..329b192 100644 --- a/tests/types/all.php +++ b/tests/types/all.php @@ -1,10 +1,12 @@ >', all([resolve(true), resolve(false)])); assertType('React\Promise\PromiseInterface>', all([resolve(true), false])); -assertType('React\Promise\PromiseInterface>', all([true, time()])); -assertType('React\Promise\PromiseInterface>', all([resolve(true), resolve(time())])); +assertType('React\Promise\PromiseInterface>', all([true, \time()])); +assertType('React\Promise\PromiseInterface>', all([resolve(true), resolve(\time())])); diff --git a/tests/types/any.php b/tests/types/any.php index 2182dd3..3fca483 100644 --- a/tests/types/any.php +++ b/tests/types/any.php @@ -1,10 +1,12 @@ ', any([resolve(true), resolve(false)])); assertType('React\Promise\PromiseInterface', any([resolve(true), false])); -assertType('React\Promise\PromiseInterface', any([true, time()])); -assertType('React\Promise\PromiseInterface', any([resolve(true), resolve(time())])); +assertType('React\Promise\PromiseInterface', any([true, \time()])); +assertType('React\Promise\PromiseInterface', any([resolve(true), resolve(\time())])); diff --git a/tests/types/deferred.php b/tests/types/deferred.php index 1596ded..e39a9e9 100644 --- a/tests/types/deferred.php +++ b/tests/types/deferred.php @@ -1,5 +1,7 @@ ', $deferred); // invalid types for arguments of $canceller /** @phpstan-ignore-next-line */ -$deferred = new Deferred(function (int $a, string $b): void {}); +$deferred = new Deferred(static function (int $a, string $b): void {}); assertType('React\Promise\Deferred', $deferred); // invalid number of arguments passed to $resolve -$deferred = new Deferred(function (callable $resolve): void { +$deferred = new Deferred(static function (callable $resolve): void { /** @phpstan-ignore-next-line */ $resolve(); }); assertType('React\Promise\Deferred', $deferred); // invalid type passed to $reject -$deferred = new Deferred(function (callable $resolve, callable $reject): void { +$deferred = new Deferred(static function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(2); }); diff --git a/tests/types/promise.php b/tests/types/promise.php index 4c73586..95733fc 100644 --- a/tests/types/promise.php +++ b/tests/types/promise.php @@ -1,5 +1,7 @@ ', $promise); // invalid types for arguments of $resolver /** @phpstan-ignore-next-line */ -$promise = new Promise(function (int $a, string $b): void {}); +$promise = new Promise(static function (int $a, string $b): void {}); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $resolve -$promise = new Promise(function (callable $resolve): void { +$promise = new Promise(static function (callable $resolve): void { /** @phpstan-ignore-next-line */ $resolve(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $reject -$promise = new Promise(function (callable $resolve, callable $reject): void { +$promise = new Promise(static function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid type passed to $reject -$promise = new Promise(function (callable $resolve, callable $reject): void { +$promise = new Promise(static function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(2); }); @@ -62,30 +64,30 @@ // invalid number of arguments for $canceller /** @phpstan-ignore-next-line */ -$promise = new Promise(function (): void {}, function ($a, $b, $c): void {}); +$promise = new Promise(static function (): void {}, static function ($a, $b, $c): void {}); // assertType('React\Promise\PromiseInterface', $promise); // invalid types for arguments of $canceller /** @phpstan-ignore-next-line */ -$promise = new Promise(function (): void {}, function (int $a, string $b): void {}); +$promise = new Promise(static function (): void {}, static function (int $a, string $b): void {}); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $resolve -$promise = new Promise(function (): void {}, function (callable $resolve): void { +$promise = new Promise(static function (): void {}, static function (callable $resolve): void { /** @phpstan-ignore-next-line */ $resolve(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid number of arguments passed to $reject -$promise = new Promise(function (): void {}, function (callable $resolve, callable $reject): void { +$promise = new Promise(static function (): void {}, static function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(); }); // assertType('React\Promise\PromiseInterface', $promise); // invalid type passed to $reject -$promise = new Promise(function (): void {}, function (callable $resolve, callable $reject): void { +$promise = new Promise(static function (): void {}, static function (callable $resolve, callable $reject): void { /** @phpstan-ignore-next-line */ $reject(2); }); diff --git a/tests/types/race.php b/tests/types/race.php index fa1a861..eaad1c6 100644 --- a/tests/types/race.php +++ b/tests/types/race.php @@ -1,10 +1,12 @@ ', race([resolve(true), resolve(false)])); assertType('React\Promise\PromiseInterface', race([resolve(true), false])); -assertType('React\Promise\PromiseInterface', race([true, time()])); -assertType('React\Promise\PromiseInterface', race([resolve(true), resolve(time())])); +assertType('React\Promise\PromiseInterface', race([true, \time()])); +assertType('React\Promise\PromiseInterface', race([resolve(true), resolve(\time())])); diff --git a/tests/types/reject.php b/tests/types/reject.php index 2dff255..6bbf067 100644 --- a/tests/types/reject.php +++ b/tests/types/reject.php @@ -1,5 +1,7 @@ ', reject(new RuntimeException())->then(function (): int { // return 42; // })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, fn(): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, fn(): PromiseInterface => resolve(42))); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, static fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, static fn(): PromiseInterface => resolve(42))); // assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(function (): bool { // return true; // }, function (): int { // return 42; // })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(fn(): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(fn(\UnexpectedValueException $e): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(fn(): PromiseInterface => resolve(42))); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(\UnexpectedValueException $e): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(function (): void {})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(function (): never { +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static function (): void {})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static function (): never { throw new \UnexpectedValueException(); })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(fn(): PromiseInterface => reject(new \UnexpectedValueException()))); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static fn(): PromiseInterface => reject(new \UnexpectedValueException()))); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(fn(): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(fn(\UnexpectedValueException $e): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(fn(): PromiseInterface => resolve(42))); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(\UnexpectedValueException $e): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(function (): void {})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(function (): never { +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static function (): void {})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static function (): never { throw new \UnexpectedValueException(); })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(fn(): PromiseInterface => reject(new \UnexpectedValueException()))); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static fn(): PromiseInterface => reject(new \UnexpectedValueException()))); diff --git a/tests/types/resolve.php b/tests/types/resolve.php index eaf0642..069e97d 100644 --- a/tests/types/resolve.php +++ b/tests/types/resolve.php @@ -1,5 +1,7 @@ ', resolve(true)); @@ -28,16 +30,16 @@ function stringOrIntPromise(): PromiseInterface assertType('React\Promise\PromiseInterface', resolve(resolve(true))); assertType('React\Promise\PromiseInterface', resolve(true)->then(null, null)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(fn(bool $bool): bool => $bool)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(fn(bool $value): int => 42)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(fn(bool $value): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $value): never { +assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $bool): bool => $bool)); +assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $value): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $value): PromiseInterface => resolve(42))); +assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $value): never { throw new \RuntimeException(); })); -assertType('React\Promise\PromiseInterface', resolve(true)->then(null, fn(\Throwable $e): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->then(null, static fn(\Throwable $e): int => 42)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(function (bool $bool): void {})); -assertType('React\Promise\PromiseInterface', resolve(false)->then(function (bool $bool): void {})->then(function (null $value): void {})); +assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $bool): void {})); +assertType('React\Promise\PromiseInterface', resolve(false)->then(static function (bool $bool): void {})->then(static function (null $value): void {})); $value = null; assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $v) use (&$value): void { @@ -45,13 +47,13 @@ function stringOrIntPromise(): PromiseInterface })); assertType('bool|null', $value); -assertType('React\Promise\PromiseInterface', resolve(true)->catch(function (\Throwable $e): never { +assertType('React\Promise\PromiseInterface', resolve(true)->catch(static function (\Throwable $e): never { throw $e; })); -assertType('React\Promise\PromiseInterface', resolve(true)->catch(fn(\Throwable $e): int => 42)); -assertType('React\Promise\PromiseInterface', resolve(true)->catch(fn(\Throwable $e): PromiseInterface => resolve(42))); +assertType('React\Promise\PromiseInterface', resolve(true)->catch(static fn(\Throwable $e): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->catch(static fn(\Throwable $e): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): void {})); +assertType('React\Promise\PromiseInterface', resolve(true)->finally(static function (): void {})); // assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): never { // throw new \RuntimeException(); // })); @@ -59,13 +61,13 @@ function stringOrIntPromise(): PromiseInterface // return reject(new \RuntimeException()); // })); -assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(function (\Throwable $e): never { +assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static function (\Throwable $e): never { throw $e; })); -assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(fn(\Throwable $e): int => 42)); -assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(fn(\Throwable $e): PromiseInterface => resolve(42))); +assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static fn(\Throwable $e): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static fn(\Throwable $e): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): void {})); +assertType('React\Promise\PromiseInterface', resolve(true)->always(static function (): void {})); // assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): never { // throw new \RuntimeException(); // })); From cf765e7fd3aab2d42fa5fe27e1c8c642d9eeba31 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 16:59:14 +0400 Subject: [PATCH 11/18] style: Apply risky Code Style rules to src --- README.md | 1 + src/Deferred.php | 2 ++ src/Exception/CompositeException.php | 2 ++ src/Exception/LengthException.php | 2 ++ src/Internal/CancellationQueue.php | 4 +++- src/Internal/FulfilledPromise.php | 9 +++++--- src/Internal/RejectedPromise.php | 4 +++- src/Promise.php | 17 +++++++++------ src/PromiseInterface.php | 2 ++ src/functions.php | 32 +++++++++++++++------------- src/functions_include.php | 2 ++ 11 files changed, 50 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 1e84dc0..2b04986 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ A lightweight implementation of [CommonJS Promises/A][CommonJS Promises/A] for P > [!NOTE] > This is a fork of [reactphp/promise][reactphp/promise] with the following improvements: > - PHP 8.1+ +> - `declare(strict_types=1);` in all the PHP files > - `@yield` annotation in the PromiseInterface > - Replaces `react/promise` v3 > - Make rejection handler reusable. `error_log()` is still used by default. diff --git a/src/Deferred.php b/src/Deferred.php index bbc6785..f51a25d 100644 --- a/src/Deferred.php +++ b/src/Deferred.php @@ -1,5 +1,7 @@ queue); isset($this->queue[$i]); $i++) { $cancellable = $this->queue[$i]; - assert(\method_exists($cancellable, 'cancel')); + \assert(\method_exists($cancellable, 'cancel')); $exception = null; diff --git a/src/Internal/FulfilledPromise.php b/src/Internal/FulfilledPromise.php index 8e72f38..edbb023 100644 --- a/src/Internal/FulfilledPromise.php +++ b/src/Internal/FulfilledPromise.php @@ -1,5 +1,7 @@ then(fn($value): PromiseInterface => - /** @var T $value */ - resolve($onFulfilledOrRejected())->then(static fn() => $value)); + return $this->then( + static fn(mixed $value): PromiseInterface => resolve($onFulfilledOrRejected()) + ->then(static fn(): mixed => $value), + ); } public function cancel(): void {} diff --git a/src/Internal/RejectedPromise.php b/src/Internal/RejectedPromise.php index d2e822e..fbf9927 100644 --- a/src/Internal/RejectedPromise.php +++ b/src/Internal/RejectedPromise.php @@ -1,5 +1,7 @@ then( null, - fn(\Throwable $reason): PromiseInterface => resolve($onFulfilledOrRejected()) + static fn(\Throwable $reason): PromiseInterface => resolve($onFulfilledOrRejected()) ->then(static fn(): PromiseInterface => new RejectedPromise($reason)), ); } diff --git a/src/Promise.php b/src/Promise.php index 1e852bd..f70224b 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -1,5 +1,7 @@ resolver($onFulfilled, $onRejected), static function () use (&$parent): void { - assert($parent instanceof self); + \assert($parent instanceof self); --$parent->requiredCancelRequests; if ($parent->requiredCancelRequests <= 0) { @@ -98,11 +100,10 @@ public function finally(callable $onFulfilledOrRejected): PromiseInterface { return $this ->then( - static fn($value): PromiseInterface => - /** @var T $value */ - resolve($onFulfilledOrRejected())->then(fn() => $value), + static fn($value): PromiseInterface => resolve($onFulfilledOrRejected()) + ->then(static fn(): mixed => $value), static fn(\Throwable $reason): PromiseInterface => resolve($onFulfilledOrRejected()) - ->then(fn(): RejectedPromise => new RejectedPromise($reason)), + ->then(static fn(): RejectedPromise => new RejectedPromise($reason)), ); } @@ -168,7 +169,9 @@ public function always(callable $onFulfilledOrRejected): PromiseInterface private function resolver(?callable $onFulfilled = null, ?callable $onRejected = null): callable { return function (callable $resolve, callable $reject) use ($onFulfilled, $onRejected): void { - $this->handlers[] = static function (PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject): void { + $this->handlers[] = static function ( + PromiseInterface $promise, + ) use ($onFulfilled, $onRejected, $resolve, $reject): void { $promise = $promise->then($onFulfilled, $onRejected); if ($promise instanceof self && $promise->result === null) { @@ -260,7 +263,7 @@ private function call(callable $cb): void } elseif (\is_object($callback) && !$callback instanceof \Closure) { $ref = new \ReflectionMethod($callback, '__invoke'); } else { - assert($callback instanceof \Closure || \is_string($callback)); + \assert($callback instanceof \Closure || \is_string($callback)); $ref = new \ReflectionFunction($callback); } $args = $ref->getNumberOfParameters(); diff --git a/src/PromiseInterface.php b/src/PromiseInterface.php index b533076..888e703 100644 --- a/src/PromiseInterface.php +++ b/src/PromiseInterface.php @@ -1,5 +1,7 @@ |T $promiseOrValue * @return PromiseInterface */ -function resolve($promiseOrValue): PromiseInterface +function resolve(mixed $promiseOrValue): PromiseInterface { if ($promiseOrValue instanceof PromiseInterface) { return $promiseOrValue; @@ -32,11 +34,11 @@ function resolve($promiseOrValue): PromiseInterface if (\method_exists($promiseOrValue, 'cancel')) { $canceller = [$promiseOrValue, 'cancel']; - assert(\is_callable($canceller)); + \assert(\is_callable($canceller)); } /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promiseOrValue): void { + return new Promise(static function (callable $resolve, callable $reject) use ($promiseOrValue): void { $promiseOrValue->then($resolve, $reject); }, $canceller); } @@ -79,7 +81,7 @@ function all(iterable $promisesOrValues): PromiseInterface $cancellationQueue = new Internal\CancellationQueue(); /** @var Promise> */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { + return new Promise(static function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { $toResolve = 0; /** @var bool */ $continue = true; @@ -91,14 +93,14 @@ function all(iterable $promisesOrValues): PromiseInterface ++$toResolve; resolve($promiseOrValue)->then( - function ($value) use ($i, &$values, &$toResolve, &$continue, $resolve): void { + static function ($value) use ($i, &$values, &$toResolve, &$continue, $resolve): void { $values[$i] = $value; if (--$toResolve === 0 && !$continue) { $resolve($values); } }, - function (\Throwable $reason) use (&$continue, $reject): void { + static function (\Throwable $reason) use (&$continue, $reject): void { $continue = false; $reject($reason); }, @@ -132,13 +134,13 @@ function race(iterable $promisesOrValues): PromiseInterface $cancellationQueue = new Internal\CancellationQueue(); /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { + return new Promise(static function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { $continue = true; foreach ($promisesOrValues as $promiseOrValue) { $cancellationQueue->enqueue($promiseOrValue); - resolve($promiseOrValue)->then($resolve, $reject)->finally(function () use (&$continue): void { + resolve($promiseOrValue)->then($resolve, $reject)->finally(static function () use (&$continue): void { $continue = false; }); @@ -169,7 +171,7 @@ function any(iterable $promisesOrValues): PromiseInterface $cancellationQueue = new Internal\CancellationQueue(); /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { + return new Promise(static function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { $toReject = 0; $continue = true; $reasons = []; @@ -179,11 +181,11 @@ function any(iterable $promisesOrValues): PromiseInterface ++$toReject; resolve($promiseOrValue)->then( - function ($value) use ($resolve, &$continue): void { + static function ($value) use ($resolve, &$continue): void { $continue = false; $resolve($value); }, - function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continue): void { + static function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continue): void { $reasons[$i] = $reason; if (--$toReject === 0 && !$continue) { @@ -274,7 +276,7 @@ function _checkTypehint(callable $callback, \Throwable $reason): bool } elseif (\is_object($callback) && !$callback instanceof \Closure) { $callbackReflection = new \ReflectionMethod($callback, '__invoke'); } else { - assert($callback instanceof \Closure || \is_string($callback)); + \assert($callback instanceof \Closure || \is_string($callback)); $callbackReflection = new \ReflectionFunction($callback); } @@ -317,15 +319,15 @@ function _checkTypehint(callable $callback, \Throwable $reason): bool if ($type instanceof \ReflectionIntersectionType) { foreach ($type->getTypes() as $typeToMatch) { - assert($typeToMatch instanceof \ReflectionNamedType); + \assert($typeToMatch instanceof \ReflectionNamedType); $name = $typeToMatch->getName(); if (!($matches = (!$typeToMatch->isBuiltin() && $reason instanceof $name))) { break; } } - assert(isset($matches)); + \assert(isset($matches)); } else { - assert($type instanceof \ReflectionNamedType); + \assert($type instanceof \ReflectionNamedType); $name = $type->getName(); $matches = !$type->isBuiltin() && $reason instanceof $name; } diff --git a/src/functions_include.php b/src/functions_include.php index 750fe6a..54b0141 100644 --- a/src/functions_include.php +++ b/src/functions_include.php @@ -1,5 +1,7 @@ Date: Wed, 27 Aug 2025 17:07:19 +0400 Subject: [PATCH 12/18] chore: Cleanup --- tests/PHP8.php | 19 ------------------- .../fixtures/CallbackWithDNFTypehintClass.php | 9 +++------ .../CallbackWithIntersectionTypehintClass.php | 11 ++--------- .../CallbackWithUnionTypehintClass.php | 11 ++--------- 4 files changed, 7 insertions(+), 43 deletions(-) delete mode 100644 tests/PHP8.php diff --git a/tests/PHP8.php b/tests/PHP8.php deleted file mode 100644 index b6f00ef..0000000 --- a/tests/PHP8.php +++ /dev/null @@ -1,19 +0,0 @@ -= 80000); - } -} diff --git a/tests/fixtures/CallbackWithDNFTypehintClass.php b/tests/fixtures/CallbackWithDNFTypehintClass.php index b7d773b..15bec34 100644 --- a/tests/fixtures/CallbackWithDNFTypehintClass.php +++ b/tests/fixtures/CallbackWithDNFTypehintClass.php @@ -7,12 +7,9 @@ class CallbackWithDNFTypehintClass { - #[PHP8] public function __invoke((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { } /* - public function __invoke(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + public function __invoke((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { } - #[PHP8] public function testCallback((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { } /* - public function testCallback(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + public function testCallback((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { } - #[PHP8] public static function testCallbackStatic((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { }/* - public static function testCallbackStatic(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + public static function testCallbackStatic((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { } } diff --git a/tests/fixtures/CallbackWithIntersectionTypehintClass.php b/tests/fixtures/CallbackWithIntersectionTypehintClass.php index 33e6b37..d028cd6 100644 --- a/tests/fixtures/CallbackWithIntersectionTypehintClass.php +++ b/tests/fixtures/CallbackWithIntersectionTypehintClass.php @@ -6,16 +6,9 @@ class CallbackWithIntersectionTypehintClass { - #[PHP8] - public static function testCallbackStatic(\RuntimeException&\Countable $e): void {}/* - public static function testCallbackStatic(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + public static function testCallbackStatic(\RuntimeException&\Countable $e): void {} - #[PHP8] public function testCallback(\RuntimeException&\Countable $e): void {} - /* - public function testCallback(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ - #[PHP8] - public function __invoke(\RuntimeException&\Countable $e): void {}/* - public function __invoke(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + public function __invoke(\RuntimeException&\Countable $e): void {} } diff --git a/tests/fixtures/CallbackWithUnionTypehintClass.php b/tests/fixtures/CallbackWithUnionTypehintClass.php index 87df75a..34533cb 100644 --- a/tests/fixtures/CallbackWithUnionTypehintClass.php +++ b/tests/fixtures/CallbackWithUnionTypehintClass.php @@ -6,16 +6,9 @@ class CallbackWithUnionTypehintClass { - #[PHP8] - public static function testCallbackStatic(\RuntimeException|\InvalidArgumentException $e): void {}/* - public static function testCallbackStatic(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + public static function testCallbackStatic(\RuntimeException|\InvalidArgumentException $e): void {} - #[PHP8] public function testCallback(\RuntimeException|\InvalidArgumentException $e): void {} - /* - public function testCallback(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ - #[PHP8] - public function __invoke(\RuntimeException|\InvalidArgumentException $e): void {}/* - public function __invoke(bool $unusedOnPhp8ButRequiredToMakePhpstanWorkOnLegacyPhp = true): void { } // */ + public function __invoke(\RuntimeException|\InvalidArgumentException $e): void {} } From c04388e819d8f5263fcb7d3bc87a829501d1b28a Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 27 Aug 2025 13:08:02 +0000 Subject: [PATCH 13/18] style(php-cs-fixer): fix coding standards --- tests/fixtures/CallbackWithDNFTypehintClass.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/fixtures/CallbackWithDNFTypehintClass.php b/tests/fixtures/CallbackWithDNFTypehintClass.php index 15bec34..5088119 100644 --- a/tests/fixtures/CallbackWithDNFTypehintClass.php +++ b/tests/fixtures/CallbackWithDNFTypehintClass.php @@ -2,14 +2,11 @@ namespace React\Promise; -use Countable; -use RuntimeException; - class CallbackWithDNFTypehintClass { - public function __invoke((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { } + public static function testCallbackStatic((\RuntimeException&\Countable)|(\RuntimeException&\IteratorAggregate) $e): void {} - public function testCallback((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { } + public function testCallback((\RuntimeException&\Countable)|(\RuntimeException&\IteratorAggregate) $e): void {} - public static function testCallbackStatic((RuntimeException&Countable)|(RuntimeException&\IteratorAggregate) $e): void { } + public function __invoke((\RuntimeException&\Countable)|(\RuntimeException&\IteratorAggregate) $e): void {} } From aca7e3d5070023f1e03b16db3d1bb4ad10ed7165 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 17:16:39 +0400 Subject: [PATCH 14/18] test: Move `phpt` tests into `Feature` directory --- .../DeferredTestCancelNoopThenRejectShouldNotReportUnhandled.phpt | 0 .../DeferredTestCancelThatRejectsShouldNotReportUnhandled.phpt | 0 tests/{ => Feature}/DeferredTestRejectShouldReportUnhandled.phpt | 0 .../DeferredTestRejectThenCancelShouldNotReportUnhandled.phpt | 0 .../FunctionAllTestRejectedShouldReportUnhandled.phpt | 0 ...stRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt | 0 .../FunctionAnyTestRejectedShouldReportUnhandled.phpt | 0 ...stRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt | 0 .../FunctionRaceTestRejectedShouldReportUnhandled.phpt | 0 ...stRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt | 0 .../FunctionRejectTestCancelShouldNotReportUnhandled.phpt | 0 .../FunctionRejectTestCatchMatchingShouldNotReportUnhandled.phpt | 0 .../FunctionRejectTestCatchMismatchShouldReportUnhandled.phpt | 0 ...FunctionRejectTestFinallyThatReturnsShouldReportUnhandled.phpt | 0 ...hrowsNewExceptionShouldReportUnhandledForNewExceptionOnly.phpt | 0 tests/{ => Feature}/FunctionRejectTestShouldReportUnhandled.phpt | 0 ...tionRejectTestShouldReportUnhandledWithPreviousExceptions.phpt | 0 ...RejectTestThenMatchingThatReturnsShouldNotReportUnhandled.phpt | 0 ...xceptionShouldReportUnhandledRejectionForNewExceptionOnly.phpt | 0 ...wsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt | 0 ...wsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt | 0 .../FunctionResolveTestThenShouldNotReportUnhandled.phpt | 0 .../FunctionSetRejectionHandlerShouldBeInvokedForUnhandled.phpt | 0 ...ionSetRejectionHandlerShouldInvokeLastHandlerForUnhandled.phpt | 0 ...nSetRejectionHandlerThatHasUnhandledShouldReportUnhandled.phpt | 0 ...ectionHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt | 0 ...sShouldTerminateProgramForUnhandledWithPreviousExceptions.phpt | 0 ...tTriggersDefaultHandlerShouldTerminateProgramForUnhandled.phpt | 0 ...sErrorHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt | 0 ...edSetRejectionHandlerShouldInvokeInnerHandlerForUnhandled.phpt | 0 ...seTestCancelThatRejectsAfterwardsShouldNotReportUnhandled.phpt | 0 .../PromiseTestCancelThatRejectsShouldNotReportUnhandled.phpt | 0 32 files changed, 0 insertions(+), 0 deletions(-) rename tests/{ => Feature}/DeferredTestCancelNoopThenRejectShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/DeferredTestCancelThatRejectsShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/DeferredTestRejectShouldReportUnhandled.phpt (100%) rename tests/{ => Feature}/DeferredTestRejectThenCancelShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionAllTestRejectedShouldReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionAllTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionAnyTestRejectedShouldReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionAnyTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRaceTestRejectedShouldReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRaceTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestCancelShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestCatchMatchingShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestCatchMismatchShouldReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestFinallyThatReturnsShouldReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestFinallyThatThrowsNewExceptionShouldReportUnhandledForNewExceptionOnly.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestShouldReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestShouldReportUnhandledWithPreviousExceptions.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestThenMatchingThatReturnsShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestThenMatchingThatThrowsNewExceptionShouldReportUnhandledRejectionForNewExceptionOnly.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt (100%) rename tests/{ => Feature}/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt (100%) rename tests/{ => Feature}/FunctionResolveTestThenShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionSetRejectionHandlerShouldBeInvokedForUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionSetRejectionHandlerShouldInvokeLastHandlerForUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionSetRejectionHandlerThatHasUnhandledShouldReportUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandledWithPreviousExceptions.phpt (100%) rename tests/{ => Feature}/FunctionSetRejectionHandlerThatTriggersDefaultHandlerShouldTerminateProgramForUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionSetRejectionHandlerThatTriggersErrorHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt (100%) rename tests/{ => Feature}/FunctionSetRejectionHandlerThatUsesNestedSetRejectionHandlerShouldInvokeInnerHandlerForUnhandled.phpt (100%) rename tests/{ => Feature}/PromiseTestCancelThatRejectsAfterwardsShouldNotReportUnhandled.phpt (100%) rename tests/{ => Feature}/PromiseTestCancelThatRejectsShouldNotReportUnhandled.phpt (100%) diff --git a/tests/DeferredTestCancelNoopThenRejectShouldNotReportUnhandled.phpt b/tests/Feature/DeferredTestCancelNoopThenRejectShouldNotReportUnhandled.phpt similarity index 100% rename from tests/DeferredTestCancelNoopThenRejectShouldNotReportUnhandled.phpt rename to tests/Feature/DeferredTestCancelNoopThenRejectShouldNotReportUnhandled.phpt diff --git a/tests/DeferredTestCancelThatRejectsShouldNotReportUnhandled.phpt b/tests/Feature/DeferredTestCancelThatRejectsShouldNotReportUnhandled.phpt similarity index 100% rename from tests/DeferredTestCancelThatRejectsShouldNotReportUnhandled.phpt rename to tests/Feature/DeferredTestCancelThatRejectsShouldNotReportUnhandled.phpt diff --git a/tests/DeferredTestRejectShouldReportUnhandled.phpt b/tests/Feature/DeferredTestRejectShouldReportUnhandled.phpt similarity index 100% rename from tests/DeferredTestRejectShouldReportUnhandled.phpt rename to tests/Feature/DeferredTestRejectShouldReportUnhandled.phpt diff --git a/tests/DeferredTestRejectThenCancelShouldNotReportUnhandled.phpt b/tests/Feature/DeferredTestRejectThenCancelShouldNotReportUnhandled.phpt similarity index 100% rename from tests/DeferredTestRejectThenCancelShouldNotReportUnhandled.phpt rename to tests/Feature/DeferredTestRejectThenCancelShouldNotReportUnhandled.phpt diff --git a/tests/FunctionAllTestRejectedShouldReportUnhandled.phpt b/tests/Feature/FunctionAllTestRejectedShouldReportUnhandled.phpt similarity index 100% rename from tests/FunctionAllTestRejectedShouldReportUnhandled.phpt rename to tests/Feature/FunctionAllTestRejectedShouldReportUnhandled.phpt diff --git a/tests/FunctionAllTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt b/tests/Feature/FunctionAllTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt similarity index 100% rename from tests/FunctionAllTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt rename to tests/Feature/FunctionAllTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt diff --git a/tests/FunctionAnyTestRejectedShouldReportUnhandled.phpt b/tests/Feature/FunctionAnyTestRejectedShouldReportUnhandled.phpt similarity index 100% rename from tests/FunctionAnyTestRejectedShouldReportUnhandled.phpt rename to tests/Feature/FunctionAnyTestRejectedShouldReportUnhandled.phpt diff --git a/tests/FunctionAnyTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt b/tests/Feature/FunctionAnyTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt similarity index 100% rename from tests/FunctionAnyTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt rename to tests/Feature/FunctionAnyTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt diff --git a/tests/FunctionRaceTestRejectedShouldReportUnhandled.phpt b/tests/Feature/FunctionRaceTestRejectedShouldReportUnhandled.phpt similarity index 100% rename from tests/FunctionRaceTestRejectedShouldReportUnhandled.phpt rename to tests/Feature/FunctionRaceTestRejectedShouldReportUnhandled.phpt diff --git a/tests/FunctionRaceTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt b/tests/Feature/FunctionRaceTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt similarity index 100% rename from tests/FunctionRaceTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt rename to tests/Feature/FunctionRaceTestRejectedThenMatchingThatReturnsShouldNotReportUnhandled.phpt diff --git a/tests/FunctionRejectTestCancelShouldNotReportUnhandled.phpt b/tests/Feature/FunctionRejectTestCancelShouldNotReportUnhandled.phpt similarity index 100% rename from tests/FunctionRejectTestCancelShouldNotReportUnhandled.phpt rename to tests/Feature/FunctionRejectTestCancelShouldNotReportUnhandled.phpt diff --git a/tests/FunctionRejectTestCatchMatchingShouldNotReportUnhandled.phpt b/tests/Feature/FunctionRejectTestCatchMatchingShouldNotReportUnhandled.phpt similarity index 100% rename from tests/FunctionRejectTestCatchMatchingShouldNotReportUnhandled.phpt rename to tests/Feature/FunctionRejectTestCatchMatchingShouldNotReportUnhandled.phpt diff --git a/tests/FunctionRejectTestCatchMismatchShouldReportUnhandled.phpt b/tests/Feature/FunctionRejectTestCatchMismatchShouldReportUnhandled.phpt similarity index 100% rename from tests/FunctionRejectTestCatchMismatchShouldReportUnhandled.phpt rename to tests/Feature/FunctionRejectTestCatchMismatchShouldReportUnhandled.phpt diff --git a/tests/FunctionRejectTestFinallyThatReturnsShouldReportUnhandled.phpt b/tests/Feature/FunctionRejectTestFinallyThatReturnsShouldReportUnhandled.phpt similarity index 100% rename from tests/FunctionRejectTestFinallyThatReturnsShouldReportUnhandled.phpt rename to tests/Feature/FunctionRejectTestFinallyThatReturnsShouldReportUnhandled.phpt diff --git a/tests/FunctionRejectTestFinallyThatThrowsNewExceptionShouldReportUnhandledForNewExceptionOnly.phpt b/tests/Feature/FunctionRejectTestFinallyThatThrowsNewExceptionShouldReportUnhandledForNewExceptionOnly.phpt similarity index 100% rename from tests/FunctionRejectTestFinallyThatThrowsNewExceptionShouldReportUnhandledForNewExceptionOnly.phpt rename to tests/Feature/FunctionRejectTestFinallyThatThrowsNewExceptionShouldReportUnhandledForNewExceptionOnly.phpt diff --git a/tests/FunctionRejectTestShouldReportUnhandled.phpt b/tests/Feature/FunctionRejectTestShouldReportUnhandled.phpt similarity index 100% rename from tests/FunctionRejectTestShouldReportUnhandled.phpt rename to tests/Feature/FunctionRejectTestShouldReportUnhandled.phpt diff --git a/tests/FunctionRejectTestShouldReportUnhandledWithPreviousExceptions.phpt b/tests/Feature/FunctionRejectTestShouldReportUnhandledWithPreviousExceptions.phpt similarity index 100% rename from tests/FunctionRejectTestShouldReportUnhandledWithPreviousExceptions.phpt rename to tests/Feature/FunctionRejectTestShouldReportUnhandledWithPreviousExceptions.phpt diff --git a/tests/FunctionRejectTestThenMatchingThatReturnsShouldNotReportUnhandled.phpt b/tests/Feature/FunctionRejectTestThenMatchingThatReturnsShouldNotReportUnhandled.phpt similarity index 100% rename from tests/FunctionRejectTestThenMatchingThatReturnsShouldNotReportUnhandled.phpt rename to tests/Feature/FunctionRejectTestThenMatchingThatReturnsShouldNotReportUnhandled.phpt diff --git a/tests/FunctionRejectTestThenMatchingThatThrowsNewExceptionShouldReportUnhandledRejectionForNewExceptionOnly.phpt b/tests/Feature/FunctionRejectTestThenMatchingThatThrowsNewExceptionShouldReportUnhandledRejectionForNewExceptionOnly.phpt similarity index 100% rename from tests/FunctionRejectTestThenMatchingThatThrowsNewExceptionShouldReportUnhandledRejectionForNewExceptionOnly.phpt rename to tests/Feature/FunctionRejectTestThenMatchingThatThrowsNewExceptionShouldReportUnhandledRejectionForNewExceptionOnly.phpt diff --git a/tests/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt b/tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt similarity index 100% rename from tests/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt rename to tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt diff --git a/tests/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt b/tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt similarity index 100% rename from tests/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt rename to tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt diff --git a/tests/FunctionResolveTestThenShouldNotReportUnhandled.phpt b/tests/Feature/FunctionResolveTestThenShouldNotReportUnhandled.phpt similarity index 100% rename from tests/FunctionResolveTestThenShouldNotReportUnhandled.phpt rename to tests/Feature/FunctionResolveTestThenShouldNotReportUnhandled.phpt diff --git a/tests/FunctionSetRejectionHandlerShouldBeInvokedForUnhandled.phpt b/tests/Feature/FunctionSetRejectionHandlerShouldBeInvokedForUnhandled.phpt similarity index 100% rename from tests/FunctionSetRejectionHandlerShouldBeInvokedForUnhandled.phpt rename to tests/Feature/FunctionSetRejectionHandlerShouldBeInvokedForUnhandled.phpt diff --git a/tests/FunctionSetRejectionHandlerShouldInvokeLastHandlerForUnhandled.phpt b/tests/Feature/FunctionSetRejectionHandlerShouldInvokeLastHandlerForUnhandled.phpt similarity index 100% rename from tests/FunctionSetRejectionHandlerShouldInvokeLastHandlerForUnhandled.phpt rename to tests/Feature/FunctionSetRejectionHandlerShouldInvokeLastHandlerForUnhandled.phpt diff --git a/tests/FunctionSetRejectionHandlerThatHasUnhandledShouldReportUnhandled.phpt b/tests/Feature/FunctionSetRejectionHandlerThatHasUnhandledShouldReportUnhandled.phpt similarity index 100% rename from tests/FunctionSetRejectionHandlerThatHasUnhandledShouldReportUnhandled.phpt rename to tests/Feature/FunctionSetRejectionHandlerThatHasUnhandledShouldReportUnhandled.phpt diff --git a/tests/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt b/tests/Feature/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt similarity index 100% rename from tests/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt rename to tests/Feature/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt diff --git a/tests/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandledWithPreviousExceptions.phpt b/tests/Feature/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandledWithPreviousExceptions.phpt similarity index 100% rename from tests/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandledWithPreviousExceptions.phpt rename to tests/Feature/FunctionSetRejectionHandlerThatThrowsShouldTerminateProgramForUnhandledWithPreviousExceptions.phpt diff --git a/tests/FunctionSetRejectionHandlerThatTriggersDefaultHandlerShouldTerminateProgramForUnhandled.phpt b/tests/Feature/FunctionSetRejectionHandlerThatTriggersDefaultHandlerShouldTerminateProgramForUnhandled.phpt similarity index 100% rename from tests/FunctionSetRejectionHandlerThatTriggersDefaultHandlerShouldTerminateProgramForUnhandled.phpt rename to tests/Feature/FunctionSetRejectionHandlerThatTriggersDefaultHandlerShouldTerminateProgramForUnhandled.phpt diff --git a/tests/FunctionSetRejectionHandlerThatTriggersErrorHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt b/tests/Feature/FunctionSetRejectionHandlerThatTriggersErrorHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt similarity index 100% rename from tests/FunctionSetRejectionHandlerThatTriggersErrorHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt rename to tests/Feature/FunctionSetRejectionHandlerThatTriggersErrorHandlerThatThrowsShouldTerminateProgramForUnhandled.phpt diff --git a/tests/FunctionSetRejectionHandlerThatUsesNestedSetRejectionHandlerShouldInvokeInnerHandlerForUnhandled.phpt b/tests/Feature/FunctionSetRejectionHandlerThatUsesNestedSetRejectionHandlerShouldInvokeInnerHandlerForUnhandled.phpt similarity index 100% rename from tests/FunctionSetRejectionHandlerThatUsesNestedSetRejectionHandlerShouldInvokeInnerHandlerForUnhandled.phpt rename to tests/Feature/FunctionSetRejectionHandlerThatUsesNestedSetRejectionHandlerShouldInvokeInnerHandlerForUnhandled.phpt diff --git a/tests/PromiseTestCancelThatRejectsAfterwardsShouldNotReportUnhandled.phpt b/tests/Feature/PromiseTestCancelThatRejectsAfterwardsShouldNotReportUnhandled.phpt similarity index 100% rename from tests/PromiseTestCancelThatRejectsAfterwardsShouldNotReportUnhandled.phpt rename to tests/Feature/PromiseTestCancelThatRejectsAfterwardsShouldNotReportUnhandled.phpt diff --git a/tests/PromiseTestCancelThatRejectsShouldNotReportUnhandled.phpt b/tests/Feature/PromiseTestCancelThatRejectsShouldNotReportUnhandled.phpt similarity index 100% rename from tests/PromiseTestCancelThatRejectsShouldNotReportUnhandled.phpt rename to tests/Feature/PromiseTestCancelThatRejectsShouldNotReportUnhandled.phpt From 942084792bc7a268897cce2a84f435539a6018fb Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 17:31:15 +0400 Subject: [PATCH 15/18] test: Separate Unit tests --- composer.json | 6 +- phpunit.xml.dist | 12 ++- tests/Fiber.php | 29 ------ tests/{ => Unit}/DeferredTest.php | 5 +- .../Fixture}/CallbackWithDNFTypehintClass.php | 2 +- .../CallbackWithIntersectionTypehintClass.php | 2 +- .../Fixture}/CallbackWithTypehintClass.php | 2 +- .../CallbackWithUnionTypehintClass.php | 2 +- .../Fixture}/CallbackWithoutTypehintClass.php | 2 +- .../Fixture}/CountableException.php | 2 +- .../Fixture}/IterableException.php | 2 +- .../Fixture}/SimpleFulfilledTestThenable.php | 2 +- .../Fixture}/SimpleTestCancellable.php | 2 +- .../SimpleTestCancellableThenable.php | 2 +- tests/{ => Unit}/FunctionAllTest.php | 8 +- tests/{ => Unit}/FunctionAnyTest.php | 8 +- .../{ => Unit}/FunctionCheckTypehintTest.php | 14 ++- tests/{ => Unit}/FunctionRaceTest.php | 7 +- tests/{ => Unit}/FunctionRejectTest.php | 4 +- tests/{ => Unit}/FunctionResolveTest.php | 11 ++- .../Internal/CancellationQueueTest.php | 9 +- .../Internal/FulfilledPromiseTest.php | 11 ++- .../Internal/RejectedPromiseTest.php | 11 ++- .../PromiseAdapter/CallbackPromiseAdapter.php | 2 +- .../PromiseAdapterInterface.php | 2 +- tests/{ => Unit}/PromiseTest.php | 5 +- .../PromiseTest/CancelTestTrait.php | 4 +- .../{ => Unit}/PromiseTest/FullTestTrait.php | 2 +- .../PromiseTest/PromiseFulfilledTestTrait.php | 4 +- .../PromiseTest/PromisePendingTestTrait.php | 4 +- .../PromiseTest/PromiseRejectedTestTrait.php | 4 +- .../PromiseTest/PromiseSettledTestTrait.php | 4 +- .../PromiseTest/RejectTestTrait.php | 4 +- .../PromiseTest/ResolveTestTrait.php | 4 +- tests/{ => Unit}/TestCase.php | 2 +- tests/types/all.php | 12 --- tests/types/any.php | 12 --- tests/types/deferred.php | 52 ---------- tests/types/promise.php | 94 ------------------- tests/types/race.php | 12 --- tests/types/reject.php | 42 --------- tests/types/resolve.php | 76 --------------- 42 files changed, 102 insertions(+), 394 deletions(-) delete mode 100644 tests/Fiber.php rename tests/{ => Unit}/DeferredTest.php (95%) rename tests/{fixtures => Unit/Fixture}/CallbackWithDNFTypehintClass.php (91%) rename tests/{fixtures => Unit/Fixture}/CallbackWithIntersectionTypehintClass.php (89%) rename tests/{fixtures => Unit/Fixture}/CallbackWithTypehintClass.php (88%) rename tests/{fixtures => Unit/Fixture}/CallbackWithUnionTypehintClass.php (90%) rename tests/{fixtures => Unit/Fixture}/CallbackWithoutTypehintClass.php (85%) rename tests/{fixtures => Unit/Fixture}/CountableException.php (82%) rename tests/{fixtures => Unit/Fixture}/IterableException.php (87%) rename tests/{fixtures => Unit/Fixture}/SimpleFulfilledTestThenable.php (87%) rename tests/{fixtures => Unit/Fixture}/SimpleTestCancellable.php (84%) rename tests/{fixtures => Unit/Fixture}/SimpleTestCancellableThenable.php (93%) rename tests/{ => Unit}/FunctionAllTest.php (95%) rename tests/{ => Unit}/FunctionAnyTest.php (97%) rename tests/{ => Unit}/FunctionCheckTypehintTest.php (93%) rename tests/{ => Unit}/FunctionRaceTest.php (97%) rename tests/{ => Unit}/FunctionRejectTest.php (87%) rename tests/{ => Unit}/FunctionResolveTest.php (94%) rename tests/{ => Unit}/Internal/CancellationQueueTest.php (91%) rename tests/{ => Unit}/Internal/FulfilledPromiseTest.php (83%) rename tests/{ => Unit}/Internal/RejectedPromiseTest.php (82%) rename tests/{ => Unit}/PromiseAdapter/CallbackPromiseAdapter.php (94%) rename tests/{ => Unit}/PromiseAdapter/PromiseAdapterInterface.php (88%) rename tests/{ => Unit}/PromiseTest.php (98%) rename tests/{ => Unit}/PromiseTest/CancelTestTrait.php (98%) rename tests/{ => Unit}/PromiseTest/FullTestTrait.php (86%) rename tests/{ => Unit}/PromiseTest/PromiseFulfilledTestTrait.php (99%) rename tests/{ => Unit}/PromiseTest/PromisePendingTestTrait.php (94%) rename tests/{ => Unit}/PromiseTest/PromiseRejectedTestTrait.php (99%) rename tests/{ => Unit}/PromiseTest/PromiseSettledTestTrait.php (95%) rename tests/{ => Unit}/PromiseTest/RejectTestTrait.php (98%) rename tests/{ => Unit}/PromiseTest/ResolveTestTrait.php (98%) rename tests/{ => Unit}/TestCase.php (97%) delete mode 100644 tests/types/all.php delete mode 100644 tests/types/any.php delete mode 100644 tests/types/deferred.php delete mode 100644 tests/types/promise.php delete mode 100644 tests/types/race.php delete mode 100644 tests/types/reject.php delete mode 100644 tests/types/resolve.php diff --git a/composer.json b/composer.json index a65b91b..b2610a1 100644 --- a/composer.json +++ b/composer.json @@ -54,10 +54,7 @@ "tests/fixtures/", "tests/" ] - }, - "files": [ - "tests/Fiber.php" - ] + } }, "config": { "audit": { @@ -69,6 +66,7 @@ "cs:fix": "php-cs-fixer fix -v", "stan": "phpstan", "test": "phpunit --color=always --testdox", + "test:unit": "phpunit --color=always --testdox --testsuite=Unit", "refactor": "rector process --config=rector.php", "test:cc": [ "@putenv XDEBUG_MODE=coverage", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 33ea968..95dc709 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,15 +2,17 @@ - - ./tests/ - ./tests/ + + ./tests/Feature + + + ./tests/Unit diff --git a/tests/Fiber.php b/tests/Fiber.php deleted file mode 100644 index 0e92bc0..0000000 --- a/tests/Fiber.php +++ /dev/null @@ -1,29 +0,0 @@ - */ class IterableException extends \RuntimeException implements \IteratorAggregate diff --git a/tests/fixtures/SimpleFulfilledTestThenable.php b/tests/Unit/Fixture/SimpleFulfilledTestThenable.php similarity index 87% rename from tests/fixtures/SimpleFulfilledTestThenable.php rename to tests/Unit/Fixture/SimpleFulfilledTestThenable.php index 59c1c2f..e32a669 100644 --- a/tests/fixtures/SimpleFulfilledTestThenable.php +++ b/tests/Unit/Fixture/SimpleFulfilledTestThenable.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit\Fixture; class SimpleFulfilledTestThenable { diff --git a/tests/fixtures/SimpleTestCancellable.php b/tests/Unit/Fixture/SimpleTestCancellable.php similarity index 84% rename from tests/fixtures/SimpleTestCancellable.php rename to tests/Unit/Fixture/SimpleTestCancellable.php index e766688..12887df 100644 --- a/tests/fixtures/SimpleTestCancellable.php +++ b/tests/Unit/Fixture/SimpleTestCancellable.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit\Fixture; class SimpleTestCancellable { diff --git a/tests/fixtures/SimpleTestCancellableThenable.php b/tests/Unit/Fixture/SimpleTestCancellableThenable.php similarity index 93% rename from tests/fixtures/SimpleTestCancellableThenable.php rename to tests/Unit/Fixture/SimpleTestCancellableThenable.php index 43155c4..f0fb21f 100644 --- a/tests/fixtures/SimpleTestCancellableThenable.php +++ b/tests/Unit/Fixture/SimpleTestCancellableThenable.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit\Fixture; class SimpleTestCancellableThenable { diff --git a/tests/FunctionAllTest.php b/tests/Unit/FunctionAllTest.php similarity index 95% rename from tests/FunctionAllTest.php rename to tests/Unit/FunctionAllTest.php index 7595547..575437e 100644 --- a/tests/FunctionAllTest.php +++ b/tests/Unit/FunctionAllTest.php @@ -2,7 +2,13 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit; + +use React\Promise\Deferred; + +use function React\Promise\all; +use function React\Promise\reject; +use function React\Promise\resolve; class FunctionAllTest extends TestCase { diff --git a/tests/FunctionAnyTest.php b/tests/Unit/FunctionAnyTest.php similarity index 97% rename from tests/FunctionAnyTest.php rename to tests/Unit/FunctionAnyTest.php index 15bfc46..5ae1b65 100644 --- a/tests/FunctionAnyTest.php +++ b/tests/Unit/FunctionAnyTest.php @@ -2,10 +2,16 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit; +use React\Promise\Deferred; use React\Promise\Exception\CompositeException; use React\Promise\Exception\LengthException; +use React\Promise\Promise; + +use function React\Promise\any; +use function React\Promise\reject; +use function React\Promise\resolve; class FunctionAnyTest extends TestCase { diff --git a/tests/FunctionCheckTypehintTest.php b/tests/Unit/FunctionCheckTypehintTest.php similarity index 93% rename from tests/FunctionCheckTypehintTest.php rename to tests/Unit/FunctionCheckTypehintTest.php index 52c2df2..4cfc116 100644 --- a/tests/FunctionCheckTypehintTest.php +++ b/tests/Unit/FunctionCheckTypehintTest.php @@ -2,7 +2,19 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit; + +use React\Promise\Unit\Fixture\CallbackWithDNFTypehintClass; +use React\Promise\Unit\Fixture\CallbackWithIntersectionTypehintClass; +use React\Promise\Unit\Fixture\CallbackWithoutTypehintClass; +use React\Promise\Unit\Fixture\CallbackWithTypehintClass; + +use React\Promise\Unit\Fixture\CallbackWithUnionTypehintClass; +use React\Promise\Unit\Fixture\CountableException; + +use React\Promise\Unit\Fixture\IterableException; + +use function React\Promise\_checkTypehint; class FunctionCheckTypehintTest extends TestCase { diff --git a/tests/FunctionRaceTest.php b/tests/Unit/FunctionRaceTest.php similarity index 97% rename from tests/FunctionRaceTest.php rename to tests/Unit/FunctionRaceTest.php index 7c263d1..b740fe9 100644 --- a/tests/FunctionRaceTest.php +++ b/tests/Unit/FunctionRaceTest.php @@ -2,7 +2,12 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit; + +use React\Promise\Deferred; +use React\Promise\Promise; + +use function React\Promise\race; class FunctionRaceTest extends TestCase { diff --git a/tests/FunctionRejectTest.php b/tests/Unit/FunctionRejectTest.php similarity index 87% rename from tests/FunctionRejectTest.php rename to tests/Unit/FunctionRejectTest.php index 8125b22..9eb5101 100644 --- a/tests/FunctionRejectTest.php +++ b/tests/Unit/FunctionRejectTest.php @@ -2,7 +2,9 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit; + +use function React\Promise\reject; class FunctionRejectTest extends TestCase { diff --git a/tests/FunctionResolveTest.php b/tests/Unit/FunctionResolveTest.php similarity index 94% rename from tests/FunctionResolveTest.php rename to tests/Unit/FunctionResolveTest.php index 7b9dc74..2dd7ce5 100644 --- a/tests/FunctionResolveTest.php +++ b/tests/Unit/FunctionResolveTest.php @@ -2,11 +2,16 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit; +use React\Promise\Unit\Fixture\SimpleFulfilledTestThenable; +use React\Promise\Unit\Fixture\SimpleTestCancellableThenable; +use React\Promise\Deferred; use React\Promise\Internal\FulfilledPromise; use React\Promise\Internal\RejectedPromise; +use function React\Promise\resolve; + class FunctionResolveTest extends TestCase { /** @@ -139,10 +144,6 @@ public function shouldSupportDeepNestingInPromiseChains(): void */ public function shouldSupportVeryDeepNestedPromises(): void { - if (PHP_VERSION_ID < 70200 && \ini_get('xdebug.max_nesting_level') !== false) { - $this->markTestSkipped('Skip unhandled rejection on legacy PHP 7.1'); - } - $deferreds = []; for ($i = 0; $i < 150; $i++) { diff --git a/tests/Internal/CancellationQueueTest.php b/tests/Unit/Internal/CancellationQueueTest.php similarity index 91% rename from tests/Internal/CancellationQueueTest.php rename to tests/Unit/Internal/CancellationQueueTest.php index e4ca3ea..a7c73df 100644 --- a/tests/Internal/CancellationQueueTest.php +++ b/tests/Unit/Internal/CancellationQueueTest.php @@ -2,12 +2,13 @@ declare(strict_types=1); -namespace React\Promise\Internal; +namespace React\Promise\Unit\Internal; use React\Promise\Deferred; -use React\Promise\SimpleTestCancellable; -use React\Promise\SimpleTestCancellableThenable; -use React\Promise\TestCase; +use React\Promise\Internal\CancellationQueue; +use React\Promise\Unit\Fixture\SimpleTestCancellable; +use React\Promise\Unit\Fixture\SimpleTestCancellableThenable; +use React\Promise\Unit\TestCase; class CancellationQueueTest extends TestCase { diff --git a/tests/Internal/FulfilledPromiseTest.php b/tests/Unit/Internal/FulfilledPromiseTest.php similarity index 83% rename from tests/Internal/FulfilledPromiseTest.php rename to tests/Unit/Internal/FulfilledPromiseTest.php index 5c2f59d..2e2c1c3 100644 --- a/tests/Internal/FulfilledPromiseTest.php +++ b/tests/Unit/Internal/FulfilledPromiseTest.php @@ -2,12 +2,13 @@ declare(strict_types=1); -namespace React\Promise\Internal; +namespace React\Promise\Unit\Internal; -use React\Promise\PromiseAdapter\CallbackPromiseAdapter; -use React\Promise\PromiseTest\PromiseFulfilledTestTrait; -use React\Promise\PromiseTest\PromiseSettledTestTrait; -use React\Promise\TestCase; +use React\Promise\Internal\FulfilledPromise; +use React\Promise\Unit\PromiseAdapter\CallbackPromiseAdapter; +use React\Promise\Unit\PromiseTest\PromiseFulfilledTestTrait; +use React\Promise\Unit\PromiseTest\PromiseSettledTestTrait; +use React\Promise\Unit\TestCase; /** * @template T diff --git a/tests/Internal/RejectedPromiseTest.php b/tests/Unit/Internal/RejectedPromiseTest.php similarity index 82% rename from tests/Internal/RejectedPromiseTest.php rename to tests/Unit/Internal/RejectedPromiseTest.php index f875936..d0a62c7 100644 --- a/tests/Internal/RejectedPromiseTest.php +++ b/tests/Unit/Internal/RejectedPromiseTest.php @@ -2,12 +2,13 @@ declare(strict_types=1); -namespace React\Promise\Internal; +namespace React\Promise\Unit\Internal; -use React\Promise\PromiseAdapter\CallbackPromiseAdapter; -use React\Promise\PromiseTest\PromiseRejectedTestTrait; -use React\Promise\PromiseTest\PromiseSettledTestTrait; -use React\Promise\TestCase; +use React\Promise\Internal\RejectedPromise; +use React\Promise\Unit\PromiseAdapter\CallbackPromiseAdapter; +use React\Promise\Unit\PromiseTest\PromiseRejectedTestTrait; +use React\Promise\Unit\PromiseTest\PromiseSettledTestTrait; +use React\Promise\Unit\TestCase; class RejectedPromiseTest extends TestCase { diff --git a/tests/PromiseAdapter/CallbackPromiseAdapter.php b/tests/Unit/PromiseAdapter/CallbackPromiseAdapter.php similarity index 94% rename from tests/PromiseAdapter/CallbackPromiseAdapter.php rename to tests/Unit/PromiseAdapter/CallbackPromiseAdapter.php index 1298098..711f820 100644 --- a/tests/PromiseAdapter/CallbackPromiseAdapter.php +++ b/tests/Unit/PromiseAdapter/CallbackPromiseAdapter.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\PromiseAdapter; +namespace React\Promise\Unit\PromiseAdapter; use React\Promise\PromiseInterface; diff --git a/tests/PromiseAdapter/PromiseAdapterInterface.php b/tests/Unit/PromiseAdapter/PromiseAdapterInterface.php similarity index 88% rename from tests/PromiseAdapter/PromiseAdapterInterface.php rename to tests/Unit/PromiseAdapter/PromiseAdapterInterface.php index e050e3f..6655c48 100644 --- a/tests/PromiseAdapter/PromiseAdapterInterface.php +++ b/tests/Unit/PromiseAdapter/PromiseAdapterInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\PromiseAdapter; +namespace React\Promise\Unit\PromiseAdapter; use React\Promise\PromiseInterface; diff --git a/tests/PromiseTest.php b/tests/Unit/PromiseTest.php similarity index 98% rename from tests/PromiseTest.php rename to tests/Unit/PromiseTest.php index 89978a8..f8a99bb 100644 --- a/tests/PromiseTest.php +++ b/tests/Unit/PromiseTest.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit; -use React\Promise\PromiseAdapter\CallbackPromiseAdapter; +use React\Promise\Promise; +use React\Promise\Unit\PromiseAdapter\CallbackPromiseAdapter; /** * @template T diff --git a/tests/PromiseTest/CancelTestTrait.php b/tests/Unit/PromiseTest/CancelTestTrait.php similarity index 98% rename from tests/PromiseTest/CancelTestTrait.php rename to tests/Unit/PromiseTest/CancelTestTrait.php index ac8e44e..8a582fd 100644 --- a/tests/PromiseTest/CancelTestTrait.php +++ b/tests/Unit/PromiseTest/CancelTestTrait.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace React\Promise\PromiseTest; +namespace React\Promise\Unit\PromiseTest; use React\Promise; -use React\Promise\PromiseAdapter\PromiseAdapterInterface; +use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; trait CancelTestTrait { diff --git a/tests/PromiseTest/FullTestTrait.php b/tests/Unit/PromiseTest/FullTestTrait.php similarity index 86% rename from tests/PromiseTest/FullTestTrait.php rename to tests/Unit/PromiseTest/FullTestTrait.php index e34ba4a..83391d0 100644 --- a/tests/PromiseTest/FullTestTrait.php +++ b/tests/Unit/PromiseTest/FullTestTrait.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\PromiseTest; +namespace React\Promise\Unit\PromiseTest; trait FullTestTrait { diff --git a/tests/PromiseTest/PromiseFulfilledTestTrait.php b/tests/Unit/PromiseTest/PromiseFulfilledTestTrait.php similarity index 99% rename from tests/PromiseTest/PromiseFulfilledTestTrait.php rename to tests/Unit/PromiseTest/PromiseFulfilledTestTrait.php index 507029b..b931a79 100644 --- a/tests/PromiseTest/PromiseFulfilledTestTrait.php +++ b/tests/Unit/PromiseTest/PromiseFulfilledTestTrait.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace React\Promise\PromiseTest; +namespace React\Promise\Unit\PromiseTest; -use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; +use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; diff --git a/tests/PromiseTest/PromisePendingTestTrait.php b/tests/Unit/PromiseTest/PromisePendingTestTrait.php similarity index 94% rename from tests/PromiseTest/PromisePendingTestTrait.php rename to tests/Unit/PromiseTest/PromisePendingTestTrait.php index 170ddf0..8f8e4c2 100644 --- a/tests/PromiseTest/PromisePendingTestTrait.php +++ b/tests/Unit/PromiseTest/PromisePendingTestTrait.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace React\Promise\PromiseTest; +namespace React\Promise\Unit\PromiseTest; -use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; +use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; trait PromisePendingTestTrait { diff --git a/tests/PromiseTest/PromiseRejectedTestTrait.php b/tests/Unit/PromiseTest/PromiseRejectedTestTrait.php similarity index 99% rename from tests/PromiseTest/PromiseRejectedTestTrait.php rename to tests/Unit/PromiseTest/PromiseRejectedTestTrait.php index afbcf2b..102b909 100644 --- a/tests/PromiseTest/PromiseRejectedTestTrait.php +++ b/tests/Unit/PromiseTest/PromiseRejectedTestTrait.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace React\Promise\PromiseTest; +namespace React\Promise\Unit\PromiseTest; -use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; +use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; diff --git a/tests/PromiseTest/PromiseSettledTestTrait.php b/tests/Unit/PromiseTest/PromiseSettledTestTrait.php similarity index 95% rename from tests/PromiseTest/PromiseSettledTestTrait.php rename to tests/Unit/PromiseTest/PromiseSettledTestTrait.php index 9b4e5a8..375cf58 100644 --- a/tests/PromiseTest/PromiseSettledTestTrait.php +++ b/tests/Unit/PromiseTest/PromiseSettledTestTrait.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace React\Promise\PromiseTest; +namespace React\Promise\Unit\PromiseTest; use React\Promise\Internal\RejectedPromise; -use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; +use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; trait PromiseSettledTestTrait { diff --git a/tests/PromiseTest/RejectTestTrait.php b/tests/Unit/PromiseTest/RejectTestTrait.php similarity index 98% rename from tests/PromiseTest/RejectTestTrait.php rename to tests/Unit/PromiseTest/RejectTestTrait.php index 044f0fb..ce0958e 100644 --- a/tests/PromiseTest/RejectTestTrait.php +++ b/tests/Unit/PromiseTest/RejectTestTrait.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace React\Promise\PromiseTest; +namespace React\Promise\Unit\PromiseTest; -use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; +use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; diff --git a/tests/PromiseTest/ResolveTestTrait.php b/tests/Unit/PromiseTest/ResolveTestTrait.php similarity index 98% rename from tests/PromiseTest/ResolveTestTrait.php rename to tests/Unit/PromiseTest/ResolveTestTrait.php index d1bcb8b..6a7e76d 100644 --- a/tests/PromiseTest/ResolveTestTrait.php +++ b/tests/Unit/PromiseTest/ResolveTestTrait.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace React\Promise\PromiseTest; +namespace React\Promise\Unit\PromiseTest; -use React\Promise\PromiseAdapter\PromiseAdapterInterface; use React\Promise\PromiseInterface; +use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; diff --git a/tests/TestCase.php b/tests/Unit/TestCase.php similarity index 97% rename from tests/TestCase.php rename to tests/Unit/TestCase.php index 5b3c0fa..31965c2 100644 --- a/tests/TestCase.php +++ b/tests/Unit/TestCase.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise; +namespace React\Promise\Unit; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase as BaseTestCase; diff --git a/tests/types/all.php b/tests/types/all.php deleted file mode 100644 index 329b192..0000000 --- a/tests/types/all.php +++ /dev/null @@ -1,12 +0,0 @@ ->', all([resolve(true), resolve(false)])); -assertType('React\Promise\PromiseInterface>', all([resolve(true), false])); -assertType('React\Promise\PromiseInterface>', all([true, \time()])); -assertType('React\Promise\PromiseInterface>', all([resolve(true), resolve(\time())])); diff --git a/tests/types/any.php b/tests/types/any.php deleted file mode 100644 index 3fca483..0000000 --- a/tests/types/any.php +++ /dev/null @@ -1,12 +0,0 @@ -', any([resolve(true), resolve(false)])); -assertType('React\Promise\PromiseInterface', any([resolve(true), false])); -assertType('React\Promise\PromiseInterface', any([true, \time()])); -assertType('React\Promise\PromiseInterface', any([resolve(true), resolve(\time())])); diff --git a/tests/types/deferred.php b/tests/types/deferred.php deleted file mode 100644 index e39a9e9..0000000 --- a/tests/types/deferred.php +++ /dev/null @@ -1,52 +0,0 @@ -', $deferredA->promise()); - -/** @var Deferred $deferredB */ -$deferredB = new Deferred(); -$deferredB->resolve(42); -assertType('React\Promise\PromiseInterface', $deferredB->promise()); - -// $deferred = new Deferred(); -// $deferred->resolve(42); -// assertType('React\Promise\Deferred', $deferred); - -// $deferred = new Deferred(); -// $deferred->resolve(true); -// $deferred->resolve('ignored'); -// assertType('React\Promise\Deferred', $deferred); - -// $deferred = new Deferred(); -// $deferred->reject(new \RuntimeException()); -// assertType('React\Promise\Deferred', $deferred); - -// invalid number of arguments passed to $canceller -/** @phpstan-ignore-next-line */ -$deferred = new Deferred(static function ($a, $b, $c): void {}); -assertType('React\Promise\Deferred', $deferred); - -// invalid types for arguments of $canceller -/** @phpstan-ignore-next-line */ -$deferred = new Deferred(static function (int $a, string $b): void {}); -assertType('React\Promise\Deferred', $deferred); - -// invalid number of arguments passed to $resolve -$deferred = new Deferred(static function (callable $resolve): void { - /** @phpstan-ignore-next-line */ - $resolve(); -}); -assertType('React\Promise\Deferred', $deferred); - -// invalid type passed to $reject -$deferred = new Deferred(static function (callable $resolve, callable $reject): void { - /** @phpstan-ignore-next-line */ - $reject(2); -}); -assertType('React\Promise\Deferred', $deferred); diff --git a/tests/types/promise.php b/tests/types/promise.php deleted file mode 100644 index 95733fc..0000000 --- a/tests/types/promise.php +++ /dev/null @@ -1,94 +0,0 @@ -', $promise); - -// $promise = new Promise(function (callable $resolve): void { -// $resolve(42); -// }); -// assertType('React\Promise\PromiseInterface', $promise); - -// $promise = new Promise(function (callable $resolve): void { -// $resolve(true); -// $resolve('ignored'); -// }); -// assertType('React\Promise\PromiseInterface', $promise); - -// $promise = new Promise(function (callable $resolve, callable $reject): void { -// $reject(new \RuntimeException()); -// }); -// assertType('React\Promise\PromiseInterface', $promise); - -// $promise = new Promise(function (): never { -// throw new \RuntimeException(); -// }); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid number of arguments for $resolver -/** @phpstan-ignore-next-line */ -$promise = new Promise(static function ($a, $b, $c): void {}); -\assert($promise instanceof Promise); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid types for arguments of $resolver -/** @phpstan-ignore-next-line */ -$promise = new Promise(static function (int $a, string $b): void {}); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid number of arguments passed to $resolve -$promise = new Promise(static function (callable $resolve): void { - /** @phpstan-ignore-next-line */ - $resolve(); -}); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid number of arguments passed to $reject -$promise = new Promise(static function (callable $resolve, callable $reject): void { - /** @phpstan-ignore-next-line */ - $reject(); -}); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid type passed to $reject -$promise = new Promise(static function (callable $resolve, callable $reject): void { - /** @phpstan-ignore-next-line */ - $reject(2); -}); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid number of arguments for $canceller -/** @phpstan-ignore-next-line */ -$promise = new Promise(static function (): void {}, static function ($a, $b, $c): void {}); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid types for arguments of $canceller -/** @phpstan-ignore-next-line */ -$promise = new Promise(static function (): void {}, static function (int $a, string $b): void {}); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid number of arguments passed to $resolve -$promise = new Promise(static function (): void {}, static function (callable $resolve): void { - /** @phpstan-ignore-next-line */ - $resolve(); -}); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid number of arguments passed to $reject -$promise = new Promise(static function (): void {}, static function (callable $resolve, callable $reject): void { - /** @phpstan-ignore-next-line */ - $reject(); -}); -// assertType('React\Promise\PromiseInterface', $promise); - -// invalid type passed to $reject -$promise = new Promise(static function (): void {}, static function (callable $resolve, callable $reject): void { - /** @phpstan-ignore-next-line */ - $reject(2); -}); -// assertType('React\Promise\PromiseInterface', $promise); diff --git a/tests/types/race.php b/tests/types/race.php deleted file mode 100644 index eaad1c6..0000000 --- a/tests/types/race.php +++ /dev/null @@ -1,12 +0,0 @@ -', race([resolve(true), resolve(false)])); -assertType('React\Promise\PromiseInterface', race([resolve(true), false])); -assertType('React\Promise\PromiseInterface', race([true, \time()])); -assertType('React\Promise\PromiseInterface', race([resolve(true), resolve(\time())])); diff --git a/tests/types/reject.php b/tests/types/reject.php deleted file mode 100644 index 6bbf067..0000000 --- a/tests/types/reject.php +++ /dev/null @@ -1,42 +0,0 @@ -', reject(new RuntimeException())); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, null)); -// assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(function (): int { -// return 42; -// })); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, static fn(): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, static fn(): PromiseInterface => resolve(42))); -// assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(function (): bool { -// return true; -// }, function (): int { -// return 42; -// })); - -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(\UnexpectedValueException $e): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(): PromiseInterface => resolve(42))); - -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static function (): void {})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static function (): never { - throw new \UnexpectedValueException(); -})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static fn(): PromiseInterface => reject(new \UnexpectedValueException()))); - -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(\UnexpectedValueException $e): int => 42)); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(): PromiseInterface => resolve(42))); - -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static function (): void {})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static function (): never { - throw new \UnexpectedValueException(); -})); -assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static fn(): PromiseInterface => reject(new \UnexpectedValueException()))); diff --git a/tests/types/resolve.php b/tests/types/resolve.php deleted file mode 100644 index 069e97d..0000000 --- a/tests/types/resolve.php +++ /dev/null @@ -1,76 +0,0 @@ - - */ -function stringOrIntPromise(): PromiseInterface -{ - return resolve(\time() % 2 ? 'string' : \time()); -}; - -assertType('React\Promise\PromiseInterface', resolve(true)); -assertType('React\Promise\PromiseInterface', resolve(stringOrInt())); -assertType('React\Promise\PromiseInterface', stringOrIntPromise()); -assertType('React\Promise\PromiseInterface', resolve(resolve(true))); - -assertType('React\Promise\PromiseInterface', resolve(true)->then(null, null)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $bool): bool => $bool)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $value): int => 42)); -assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $value): PromiseInterface => resolve(42))); -assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $value): never { - throw new \RuntimeException(); -})); -assertType('React\Promise\PromiseInterface', resolve(true)->then(null, static fn(\Throwable $e): int => 42)); - -assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $bool): void {})); -assertType('React\Promise\PromiseInterface', resolve(false)->then(static function (bool $bool): void {})->then(static function (null $value): void {})); - -$value = null; -assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $v) use (&$value): void { - $value = $v; -})); -assertType('bool|null', $value); - -assertType('React\Promise\PromiseInterface', resolve(true)->catch(static function (\Throwable $e): never { - throw $e; -})); -assertType('React\Promise\PromiseInterface', resolve(true)->catch(static fn(\Throwable $e): int => 42)); -assertType('React\Promise\PromiseInterface', resolve(true)->catch(static fn(\Throwable $e): PromiseInterface => resolve(42))); - -assertType('React\Promise\PromiseInterface', resolve(true)->finally(static function (): void {})); -// assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): never { -// throw new \RuntimeException(); -// })); -// assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): PromiseInterface { -// return reject(new \RuntimeException()); -// })); - -assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static function (\Throwable $e): never { - throw $e; -})); -assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static fn(\Throwable $e): int => 42)); -assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static fn(\Throwable $e): PromiseInterface => resolve(42))); - -assertType('React\Promise\PromiseInterface', resolve(true)->always(static function (): void {})); -// assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): never { -// throw new \RuntimeException(); -// })); -// assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): PromiseInterface { -// return reject(new \RuntimeException()); -// })); From f943b81d154e49d48c3e1b0e491639ea702cbf15 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 17:45:21 +0400 Subject: [PATCH 16/18] test: Fix namespaces; add Arch tests; update PHPUnit to v10 --- composer.json | 10 +- phpunit.xml.dist | 21 ++++- rector.php | 3 + tests/Arch/ArchTest.php | 40 ++++++++ ...ReportUnhandledForTypeErrorOnlyOnPhp7.phpt | 25 ----- ...ReportUnhandledForTypeErrorOnlyOnPhp8.phpt | 25 ----- tests/Types/all.php | 12 +++ tests/Types/any.php | 12 +++ tests/Types/deferred.php | 52 ++++++++++ tests/Types/promise.php | 94 +++++++++++++++++++ tests/Types/race.php | 12 +++ tests/Types/reject.php | 42 +++++++++ tests/Types/resolve.php | 76 +++++++++++++++ tests/Unit/DeferredTest.php | 17 ++-- .../Fixture/CallbackWithDNFTypehintClass.php | 2 +- .../CallbackWithIntersectionTypehintClass.php | 2 +- .../Fixture/CallbackWithTypehintClass.php | 2 +- .../CallbackWithUnionTypehintClass.php | 2 +- .../Fixture/CallbackWithoutTypehintClass.php | 2 +- tests/Unit/Fixture/CountableException.php | 2 +- tests/Unit/Fixture/IterableException.php | 2 +- .../Fixture/SimpleFulfilledTestThenable.php | 2 +- tests/Unit/Fixture/SimpleTestCancellable.php | 2 +- .../Fixture/SimpleTestCancellableThenable.php | 2 +- tests/Unit/FunctionAllTest.php | 39 +++----- tests/Unit/FunctionAnyTest.php | 55 +++-------- tests/Unit/FunctionCheckTypehintTest.php | 79 ++++++---------- tests/Unit/FunctionRaceTest.php | 43 +++------ tests/Unit/FunctionRejectTest.php | 8 +- tests/Unit/FunctionResolveTest.php | 35 +++---- tests/Unit/Internal/CancellationQueueTest.php | 33 +++---- tests/Unit/Internal/FulfilledPromiseTest.php | 15 ++- tests/Unit/Internal/RejectedPromiseTest.php | 10 +- .../PromiseAdapter/CallbackPromiseAdapter.php | 2 +- .../PromiseAdapterInterface.php | 2 +- tests/Unit/PromiseTest.php | 57 ++++------- tests/Unit/PromiseTest/CancelTestTrait.php | 73 ++++---------- tests/Unit/PromiseTest/FullTestTrait.php | 2 +- .../PromiseTest/PromiseFulfilledTestTrait.php | 75 +++++---------- .../PromiseTest/PromisePendingTestTrait.php | 25 ++--- .../PromiseTest/PromiseRejectedTestTrait.php | 91 ++++++------------ .../PromiseTest/PromiseSettledTestTrait.php | 23 ++--- tests/Unit/PromiseTest/RejectTestTrait.php | 41 +++----- tests/Unit/PromiseTest/ResolveTestTrait.php | 53 +++-------- tests/Unit/TestCase.php | 4 +- 45 files changed, 626 insertions(+), 600 deletions(-) create mode 100644 tests/Arch/ArchTest.php delete mode 100644 tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt delete mode 100644 tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt create mode 100644 tests/Types/all.php create mode 100644 tests/Types/any.php create mode 100644 tests/Types/deferred.php create mode 100644 tests/Types/promise.php create mode 100644 tests/Types/race.php create mode 100644 tests/Types/reject.php create mode 100644 tests/Types/resolve.php diff --git a/composer.json b/composer.json index b2610a1..ac4769b 100644 --- a/composer.json +++ b/composer.json @@ -36,9 +36,10 @@ }, "require-dev": { "phpstan/phpstan": "1.12.28", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^10.5", "rector/rector": "^1.2", - "spiral/code-style": "^2.2" + "spiral/code-style": "^2.2", + "ta-tikoma/phpunit-architecture-test": "^0.8.5" }, "autoload": { "psr-4": { @@ -50,8 +51,7 @@ }, "autoload-dev": { "psr-4": { - "React\\Promise\\": [ - "tests/fixtures/", + "React\\Promise\\Tests\\": [ "tests/" ] } @@ -66,6 +66,8 @@ "cs:fix": "php-cs-fixer fix -v", "stan": "phpstan", "test": "phpunit --color=always --testdox", + "test:arch": "phpunit --color=always --testdox --testsuite=Arch", + "test:feat": "phpunit --color=always --testdox --testsuite=Feature", "test:unit": "phpunit --color=always --testdox --testsuite=Unit", "refactor": "rector process --config=rector.php", "test:cc": [ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 95dc709..7d0eb26 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -6,8 +6,11 @@ bootstrap="vendor/autoload.php" cacheResultFile="runtime/phpunit/result.cache" colors="true" - convertDeprecationsToExceptions="true"> +> + + ./tests/Arch + ./tests/Feature @@ -16,13 +19,23 @@ + + + + + + + + + + - ./src/ + src - ./src/functions_include.php + tests - + diff --git a/rector.php b/rector.php index c2b1065..acab7ac 100644 --- a/rector.php +++ b/rector.php @@ -11,6 +11,9 @@ ]) // uncomment to reach your current PHP version // ->withPhpSets(php81: true) + // ->withSets([ + // \Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_100, + // ]) ->withTypeCoverageLevel(0) ->withDeadCodeLevel(0) ->withCodeQualityLevel(0); diff --git a/tests/Arch/ArchTest.php b/tests/Arch/ArchTest.php new file mode 100644 index 0000000..d47ad05 --- /dev/null +++ b/tests/Arch/ArchTest.php @@ -0,0 +1,40 @@ +layer(); + + foreach ($layer as $object) { + foreach ($object->uses as $use) { + foreach ($functions as $function) { + $function === $use and throw new \Exception( + \sprintf( + 'Function `%s()` is used in %s.', + $function, + $object->name, + ), + ); + } + } + } + + $this->assertTrue(true); + } +} diff --git a/tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt b/tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt deleted file mode 100644 index bbf01c4..0000000 --- a/tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp7.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -Calling reject() and then then() with invalid type should report unhandled rejection for TypeError ---SKIPIF-- -= 80000) die("Skipped: PHP 7 only."); ?> ---INI-- -# suppress legacy PHPUnit 7 warning for Xdebug 3 -xdebug.default_enable= ---FILE-- -then(null, function (UnexpectedValueException $unexpected): void { // @phpstan-ignore-line - echo 'This will never be shown because the types do not match' . PHP_EOL; -}); - -?> ---EXPECTF-- -Unhandled promise rejection with TypeError: Argument 1 passed to {closure}() must be an instance of UnexpectedValueException, instance of RuntimeException given, called in %s/src/Internal/RejectedPromise.php on line %d and defined in %s:%d -Stack trace: -#0 %s/src/Internal/RejectedPromise.php(%d): {closure}(%S) -#1 %s(%d): React\Promise\Internal\RejectedPromise->then(%S) -#2 %A{main} diff --git a/tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt b/tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt deleted file mode 100644 index 698f7ec..0000000 --- a/tests/Feature/FunctionRejectTestThenMismatchThrowsTypeErrorAndShouldReportUnhandledForTypeErrorOnlyOnPhp8.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -Calling reject() and then then() with invalid type should report unhandled rejection for TypeError ---SKIPIF-- - ---INI-- -# suppress legacy PHPUnit 7 warning for Xdebug 3 -xdebug.default_enable= ---FILE-- -then(null, function (UnexpectedValueException $unexpected): void { // @phpstan-ignore-line - echo 'This will never be shown because the types do not match' . PHP_EOL; -}); - -?> ---EXPECTF-- -Unhandled promise rejection with TypeError: {closure%S}(): Argument #1 ($unexpected) must be of type UnexpectedValueException, RuntimeException given, called in %s/src/Internal/RejectedPromise.php on line %d and defined in %s:%d -Stack trace: -#0 %s/src/Internal/RejectedPromise.php(%d): {closure%S}(%S) -#1 %s(%d): React\Promise\Internal\RejectedPromise->then(%S) -#2 %A{main} diff --git a/tests/Types/all.php b/tests/Types/all.php new file mode 100644 index 0000000..329b192 --- /dev/null +++ b/tests/Types/all.php @@ -0,0 +1,12 @@ +>', all([resolve(true), resolve(false)])); +assertType('React\Promise\PromiseInterface>', all([resolve(true), false])); +assertType('React\Promise\PromiseInterface>', all([true, \time()])); +assertType('React\Promise\PromiseInterface>', all([resolve(true), resolve(\time())])); diff --git a/tests/Types/any.php b/tests/Types/any.php new file mode 100644 index 0000000..3fca483 --- /dev/null +++ b/tests/Types/any.php @@ -0,0 +1,12 @@ +', any([resolve(true), resolve(false)])); +assertType('React\Promise\PromiseInterface', any([resolve(true), false])); +assertType('React\Promise\PromiseInterface', any([true, \time()])); +assertType('React\Promise\PromiseInterface', any([resolve(true), resolve(\time())])); diff --git a/tests/Types/deferred.php b/tests/Types/deferred.php new file mode 100644 index 0000000..e39a9e9 --- /dev/null +++ b/tests/Types/deferred.php @@ -0,0 +1,52 @@ +', $deferredA->promise()); + +/** @var Deferred $deferredB */ +$deferredB = new Deferred(); +$deferredB->resolve(42); +assertType('React\Promise\PromiseInterface', $deferredB->promise()); + +// $deferred = new Deferred(); +// $deferred->resolve(42); +// assertType('React\Promise\Deferred', $deferred); + +// $deferred = new Deferred(); +// $deferred->resolve(true); +// $deferred->resolve('ignored'); +// assertType('React\Promise\Deferred', $deferred); + +// $deferred = new Deferred(); +// $deferred->reject(new \RuntimeException()); +// assertType('React\Promise\Deferred', $deferred); + +// invalid number of arguments passed to $canceller +/** @phpstan-ignore-next-line */ +$deferred = new Deferred(static function ($a, $b, $c): void {}); +assertType('React\Promise\Deferred', $deferred); + +// invalid types for arguments of $canceller +/** @phpstan-ignore-next-line */ +$deferred = new Deferred(static function (int $a, string $b): void {}); +assertType('React\Promise\Deferred', $deferred); + +// invalid number of arguments passed to $resolve +$deferred = new Deferred(static function (callable $resolve): void { + /** @phpstan-ignore-next-line */ + $resolve(); +}); +assertType('React\Promise\Deferred', $deferred); + +// invalid type passed to $reject +$deferred = new Deferred(static function (callable $resolve, callable $reject): void { + /** @phpstan-ignore-next-line */ + $reject(2); +}); +assertType('React\Promise\Deferred', $deferred); diff --git a/tests/Types/promise.php b/tests/Types/promise.php new file mode 100644 index 0000000..95733fc --- /dev/null +++ b/tests/Types/promise.php @@ -0,0 +1,94 @@ +', $promise); + +// $promise = new Promise(function (callable $resolve): void { +// $resolve(42); +// }); +// assertType('React\Promise\PromiseInterface', $promise); + +// $promise = new Promise(function (callable $resolve): void { +// $resolve(true); +// $resolve('ignored'); +// }); +// assertType('React\Promise\PromiseInterface', $promise); + +// $promise = new Promise(function (callable $resolve, callable $reject): void { +// $reject(new \RuntimeException()); +// }); +// assertType('React\Promise\PromiseInterface', $promise); + +// $promise = new Promise(function (): never { +// throw new \RuntimeException(); +// }); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid number of arguments for $resolver +/** @phpstan-ignore-next-line */ +$promise = new Promise(static function ($a, $b, $c): void {}); +\assert($promise instanceof Promise); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid types for arguments of $resolver +/** @phpstan-ignore-next-line */ +$promise = new Promise(static function (int $a, string $b): void {}); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid number of arguments passed to $resolve +$promise = new Promise(static function (callable $resolve): void { + /** @phpstan-ignore-next-line */ + $resolve(); +}); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid number of arguments passed to $reject +$promise = new Promise(static function (callable $resolve, callable $reject): void { + /** @phpstan-ignore-next-line */ + $reject(); +}); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid type passed to $reject +$promise = new Promise(static function (callable $resolve, callable $reject): void { + /** @phpstan-ignore-next-line */ + $reject(2); +}); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid number of arguments for $canceller +/** @phpstan-ignore-next-line */ +$promise = new Promise(static function (): void {}, static function ($a, $b, $c): void {}); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid types for arguments of $canceller +/** @phpstan-ignore-next-line */ +$promise = new Promise(static function (): void {}, static function (int $a, string $b): void {}); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid number of arguments passed to $resolve +$promise = new Promise(static function (): void {}, static function (callable $resolve): void { + /** @phpstan-ignore-next-line */ + $resolve(); +}); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid number of arguments passed to $reject +$promise = new Promise(static function (): void {}, static function (callable $resolve, callable $reject): void { + /** @phpstan-ignore-next-line */ + $reject(); +}); +// assertType('React\Promise\PromiseInterface', $promise); + +// invalid type passed to $reject +$promise = new Promise(static function (): void {}, static function (callable $resolve, callable $reject): void { + /** @phpstan-ignore-next-line */ + $reject(2); +}); +// assertType('React\Promise\PromiseInterface', $promise); diff --git a/tests/Types/race.php b/tests/Types/race.php new file mode 100644 index 0000000..eaad1c6 --- /dev/null +++ b/tests/Types/race.php @@ -0,0 +1,12 @@ +', race([resolve(true), resolve(false)])); +assertType('React\Promise\PromiseInterface', race([resolve(true), false])); +assertType('React\Promise\PromiseInterface', race([true, \time()])); +assertType('React\Promise\PromiseInterface', race([resolve(true), resolve(\time())])); diff --git a/tests/Types/reject.php b/tests/Types/reject.php new file mode 100644 index 0000000..6bbf067 --- /dev/null +++ b/tests/Types/reject.php @@ -0,0 +1,42 @@ +', reject(new RuntimeException())); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, null)); +// assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(function (): int { +// return 42; +// })); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, static fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(null, static fn(): PromiseInterface => resolve(42))); +// assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->then(function (): bool { +// return true; +// }, function (): int { +// return 42; +// })); + +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(\UnexpectedValueException $e): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->catch(static fn(): PromiseInterface => resolve(42))); + +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static function (): void {})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static function (): never { + throw new \UnexpectedValueException(); +})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->finally(static fn(): PromiseInterface => reject(new \UnexpectedValueException()))); + +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(\UnexpectedValueException $e): int => 42)); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->otherwise(static fn(): PromiseInterface => resolve(42))); + +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static function (): void {})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static function (): never { + throw new \UnexpectedValueException(); +})); +assertType('React\Promise\PromiseInterface', reject(new RuntimeException())->always(static fn(): PromiseInterface => reject(new \UnexpectedValueException()))); diff --git a/tests/Types/resolve.php b/tests/Types/resolve.php new file mode 100644 index 0000000..069e97d --- /dev/null +++ b/tests/Types/resolve.php @@ -0,0 +1,76 @@ + + */ +function stringOrIntPromise(): PromiseInterface +{ + return resolve(\time() % 2 ? 'string' : \time()); +}; + +assertType('React\Promise\PromiseInterface', resolve(true)); +assertType('React\Promise\PromiseInterface', resolve(stringOrInt())); +assertType('React\Promise\PromiseInterface', stringOrIntPromise()); +assertType('React\Promise\PromiseInterface', resolve(resolve(true))); + +assertType('React\Promise\PromiseInterface', resolve(true)->then(null, null)); +assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $bool): bool => $bool)); +assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $value): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->then(static fn(bool $value): PromiseInterface => resolve(42))); +assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $value): never { + throw new \RuntimeException(); +})); +assertType('React\Promise\PromiseInterface', resolve(true)->then(null, static fn(\Throwable $e): int => 42)); + +assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $bool): void {})); +assertType('React\Promise\PromiseInterface', resolve(false)->then(static function (bool $bool): void {})->then(static function (null $value): void {})); + +$value = null; +assertType('React\Promise\PromiseInterface', resolve(true)->then(static function (bool $v) use (&$value): void { + $value = $v; +})); +assertType('bool|null', $value); + +assertType('React\Promise\PromiseInterface', resolve(true)->catch(static function (\Throwable $e): never { + throw $e; +})); +assertType('React\Promise\PromiseInterface', resolve(true)->catch(static fn(\Throwable $e): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->catch(static fn(\Throwable $e): PromiseInterface => resolve(42))); + +assertType('React\Promise\PromiseInterface', resolve(true)->finally(static function (): void {})); +// assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): never { +// throw new \RuntimeException(); +// })); +// assertType('React\Promise\PromiseInterface', resolve(true)->finally(function (): PromiseInterface { +// return reject(new \RuntimeException()); +// })); + +assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static function (\Throwable $e): never { + throw $e; +})); +assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static fn(\Throwable $e): int => 42)); +assertType('React\Promise\PromiseInterface', resolve(true)->otherwise(static fn(\Throwable $e): PromiseInterface => resolve(42))); + +assertType('React\Promise\PromiseInterface', resolve(true)->always(static function (): void {})); +// assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): never { +// throw new \RuntimeException(); +// })); +// assertType('React\Promise\PromiseInterface', resolve(true)->always(function (): PromiseInterface { +// return reject(new \RuntimeException()); +// })); diff --git a/tests/Unit/DeferredTest.php b/tests/Unit/DeferredTest.php index 6db8e56..065e5b4 100644 --- a/tests/Unit/DeferredTest.php +++ b/tests/Unit/DeferredTest.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; +use PHPUnit\Framework\Attributes\Test; use React\Promise\Deferred; -use React\Promise\Unit\PromiseAdapter\CallbackPromiseAdapter; +use React\Promise\Tests\Unit\PromiseAdapter\CallbackPromiseAdapter; /** * @template T @@ -29,9 +30,7 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm ]); } - /** - * @test - */ + #[Test] public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException(): void { \gc_collect_cycles(); @@ -44,9 +43,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithEx $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException(): void { \gc_collect_cycles(); @@ -61,9 +58,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejects $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenceAndExplicitlyRejectWithException(): void { \gc_collect_cycles(); diff --git a/tests/Unit/Fixture/CallbackWithDNFTypehintClass.php b/tests/Unit/Fixture/CallbackWithDNFTypehintClass.php index c2fbc3a..597dd3c 100644 --- a/tests/Unit/Fixture/CallbackWithDNFTypehintClass.php +++ b/tests/Unit/Fixture/CallbackWithDNFTypehintClass.php @@ -1,6 +1,6 @@ */ class IterableException extends \RuntimeException implements \IteratorAggregate diff --git a/tests/Unit/Fixture/SimpleFulfilledTestThenable.php b/tests/Unit/Fixture/SimpleFulfilledTestThenable.php index e32a669..821d349 100644 --- a/tests/Unit/Fixture/SimpleFulfilledTestThenable.php +++ b/tests/Unit/Fixture/SimpleFulfilledTestThenable.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\Unit\Fixture; +namespace React\Promise\Tests\Unit\Fixture; class SimpleFulfilledTestThenable { diff --git a/tests/Unit/Fixture/SimpleTestCancellable.php b/tests/Unit/Fixture/SimpleTestCancellable.php index 12887df..811c73d 100644 --- a/tests/Unit/Fixture/SimpleTestCancellable.php +++ b/tests/Unit/Fixture/SimpleTestCancellable.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\Unit\Fixture; +namespace React\Promise\Tests\Unit\Fixture; class SimpleTestCancellable { diff --git a/tests/Unit/Fixture/SimpleTestCancellableThenable.php b/tests/Unit/Fixture/SimpleTestCancellableThenable.php index f0fb21f..871cffa 100644 --- a/tests/Unit/Fixture/SimpleTestCancellableThenable.php +++ b/tests/Unit/Fixture/SimpleTestCancellableThenable.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\Unit\Fixture; +namespace React\Promise\Tests\Unit\Fixture; class SimpleTestCancellableThenable { diff --git a/tests/Unit/FunctionAllTest.php b/tests/Unit/FunctionAllTest.php index 575437e..9735684 100644 --- a/tests/Unit/FunctionAllTest.php +++ b/tests/Unit/FunctionAllTest.php @@ -2,8 +2,9 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; +use PHPUnit\Framework\Attributes\Test; use React\Promise\Deferred; use function React\Promise\all; @@ -12,9 +13,7 @@ class FunctionAllTest extends TestCase { - /** - * @test - */ + #[Test] public function shouldResolveEmptyInput(): void { $mock = $this->createCallableMock(); @@ -27,9 +26,7 @@ public function shouldResolveEmptyInput(): void ->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveValuesArray(): void { $mock = $this->createCallableMock(); @@ -42,9 +39,7 @@ public function shouldResolveValuesArray(): void ->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolvePromisesArray(): void { $mock = $this->createCallableMock(); @@ -57,9 +52,7 @@ public function shouldResolvePromisesArray(): void ->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveSparseArrayInput(): void { $mock = $this->createCallableMock(); @@ -72,9 +65,7 @@ public function shouldResolveSparseArrayInput(): void ->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveValuesGenerator(): void { $mock = $this->createCallableMock(); @@ -92,9 +83,7 @@ public function shouldResolveValuesGenerator(): void all($gen)->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveValuesGeneratorEmpty(): void { $mock = $this->createCallableMock(); @@ -112,9 +101,7 @@ public function shouldResolveValuesGeneratorEmpty(): void all($gen)->then($mock); } - /** - * @test - */ + #[Test] public function shouldRejectIfAnyInputPromiseRejects(): void { $exception2 = new \Exception(); @@ -130,9 +117,7 @@ public function shouldRejectIfAnyInputPromiseRejects(): void ->then($this->expectCallableNever(), $mock); } - /** - * @test - */ + #[Test] public function shouldRejectInfiteGeneratorOrRejectedPromises(): void { $mock = $this->createCallableMock(); @@ -150,9 +135,7 @@ public function shouldRejectInfiteGeneratorOrRejectedPromises(): void all($gen)->then(null, $mock); } - /** - * @test - */ + #[Test] public function shouldPreserveTheOrderOfArrayWhenResolvingAsyncPromises(): void { $mock = $this->createCallableMock(); diff --git a/tests/Unit/FunctionAnyTest.php b/tests/Unit/FunctionAnyTest.php index 5ae1b65..99e42f1 100644 --- a/tests/Unit/FunctionAnyTest.php +++ b/tests/Unit/FunctionAnyTest.php @@ -2,8 +2,9 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; +use PHPUnit\Framework\Attributes\Test; use React\Promise\Deferred; use React\Promise\Exception\CompositeException; use React\Promise\Exception\LengthException; @@ -15,9 +16,7 @@ class FunctionAnyTest extends TestCase { - /** - * @test - */ + #[Test] public function shouldRejectWithLengthExceptionWithEmptyInputArray(): void { $mock = $this->createCallableMock(); @@ -33,9 +32,7 @@ public function shouldRejectWithLengthExceptionWithEmptyInputArray(): void ->then($this->expectCallableNever(), $mock); } - /** - * @test - */ + #[Test] public function shouldRejectWithLengthExceptionWithEmptyInputGenerator(): void { $mock = $this->createCallableMock(); @@ -53,9 +50,7 @@ public function shouldRejectWithLengthExceptionWithEmptyInputGenerator(): void any($gen)->then($this->expectCallableNever(), $mock); } - /** - * @test - */ + #[Test] public function shouldResolveWithAnInputValue(): void { $mock = $this->createCallableMock(); @@ -68,9 +63,7 @@ public function shouldResolveWithAnInputValue(): void ->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveWithAPromisedInputValue(): void { $mock = $this->createCallableMock(); @@ -83,9 +76,7 @@ public function shouldResolveWithAPromisedInputValue(): void ->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveWithAnInputValueFromDeferred(): void { $mock = $this->createCallableMock(); @@ -101,9 +92,7 @@ public function shouldResolveWithAnInputValueFromDeferred(): void $deferred->resolve(1); } - /** - * @test - */ + #[Test] public function shouldResolveValuesGenerator(): void { $mock = $this->createCallableMock(); @@ -121,9 +110,7 @@ public function shouldResolveValuesGenerator(): void any($gen)->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveValuesInfiniteGenerator(): void { $mock = $this->createCallableMock(); @@ -141,9 +128,7 @@ public function shouldResolveValuesInfiniteGenerator(): void any($gen)->then($mock); } - /** - * @test - */ + #[Test] public function shouldRejectWithAllRejectedInputValuesIfAllInputsAreRejected(): void { $exception1 = new \Exception(); @@ -165,9 +150,7 @@ public function shouldRejectWithAllRejectedInputValuesIfAllInputsAreRejected(): ->then($this->expectCallableNever(), $mock); } - /** - * @test - */ + #[Test] public function shouldRejectWithAllRejectedInputValuesIfInputIsRejectedFromDeferred(): void { $exception = new \Exception(); @@ -190,9 +173,7 @@ public function shouldRejectWithAllRejectedInputValuesIfInputIsRejectedFromDefer $deferred->reject($exception); } - /** - * @test - */ + #[Test] public function shouldResolveWhenFirstInputPromiseResolves(): void { $exception2 = new \Exception(); @@ -208,9 +189,7 @@ public function shouldResolveWhenFirstInputPromiseResolves(): void ->then($mock); } - /** - * @test - */ + #[Test] public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue(): void { $mock = $this->createCallableMock(); @@ -229,9 +208,7 @@ public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue $d1->resolve(1); } - /** - * @test - */ + #[Test] public function shouldCancelInputArrayPromises(): void { $promise1 = new Promise(static function (): void {}, $this->expectCallableOnce()); @@ -240,9 +217,7 @@ public function shouldCancelInputArrayPromises(): void any([$promise1, $promise2])->cancel(); } - /** - * @test - */ + #[Test] public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfills(): void { $deferred = new Deferred($this->expectCallableNever()); diff --git a/tests/Unit/FunctionCheckTypehintTest.php b/tests/Unit/FunctionCheckTypehintTest.php index 4cfc116..16b653d 100644 --- a/tests/Unit/FunctionCheckTypehintTest.php +++ b/tests/Unit/FunctionCheckTypehintTest.php @@ -2,61 +2,50 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; -use React\Promise\Unit\Fixture\CallbackWithDNFTypehintClass; -use React\Promise\Unit\Fixture\CallbackWithIntersectionTypehintClass; -use React\Promise\Unit\Fixture\CallbackWithoutTypehintClass; -use React\Promise\Unit\Fixture\CallbackWithTypehintClass; - -use React\Promise\Unit\Fixture\CallbackWithUnionTypehintClass; -use React\Promise\Unit\Fixture\CountableException; - -use React\Promise\Unit\Fixture\IterableException; +use PHPUnit\Framework\Attributes\Test; +use React\Promise\Tests\Unit\Fixture\CallbackWithDNFTypehintClass; +use React\Promise\Tests\Unit\Fixture\CallbackWithIntersectionTypehintClass; +use React\Promise\Tests\Unit\Fixture\CallbackWithoutTypehintClass; +use React\Promise\Tests\Unit\Fixture\CallbackWithTypehintClass; +use React\Promise\Tests\Unit\Fixture\CallbackWithUnionTypehintClass; +use React\Promise\Tests\Unit\Fixture\CountableException; +use React\Promise\Tests\Unit\Fixture\IterableException; use function React\Promise\_checkTypehint; class FunctionCheckTypehintTest extends TestCase { - /** - * @test - */ + #[Test] public function shouldAcceptClosureCallbackWithTypehint(): void { self::assertTrue(_checkTypehint(static function (\InvalidArgumentException $e): void {}, new \InvalidArgumentException())); self::assertFalse(_checkTypehint(static function (\InvalidArgumentException $e): void {}, new \Exception())); } - /** - * @test - */ + #[Test] public function shouldAcceptFunctionStringCallbackWithTypehint(): void { self::assertTrue(_checkTypehint(new CallbackWithTypehintClass(), new \InvalidArgumentException())); self::assertFalse(_checkTypehint(new CallbackWithTypehintClass(), new \Exception())); } - /** - * @test - */ + #[Test] public function shouldAcceptInvokableObjectCallbackWithTypehint(): void { self::assertTrue(_checkTypehint(new CallbackWithTypehintClass(), new \InvalidArgumentException())); self::assertFalse(_checkTypehint(new CallbackWithTypehintClass(), new \Exception())); } - /** - * @test - */ + #[Test] public function shouldAcceptObjectMethodCallbackWithTypehint(): void { self::assertTrue(_checkTypehint([new CallbackWithTypehintClass(), 'testCallback'], new \InvalidArgumentException())); self::assertFalse(_checkTypehint([new CallbackWithTypehintClass(), 'testCallback'], new \Exception())); } - /** - * @test - */ + #[Test] public function shouldAcceptStaticClassCallbackWithTypehint(): void { self::assertTrue(_checkTypehint([CallbackWithTypehintClass::class, 'testCallbackStatic'], new \InvalidArgumentException())); @@ -64,9 +53,9 @@ public function shouldAcceptStaticClassCallbackWithTypehint(): void } /** - * @test * @requires PHP 8 */ + #[Test] public function shouldAcceptClosureCallbackWithUnionTypehint(): void { eval( @@ -77,9 +66,9 @@ public function shouldAcceptClosureCallbackWithUnionTypehint(): void } /** - * @test * @requires PHP 8 */ + #[Test] public function shouldAcceptInvokableObjectCallbackWithUnionTypehint(): void { self::assertTrue(_checkTypehint(new CallbackWithUnionTypehintClass(), new \InvalidArgumentException())); @@ -87,9 +76,9 @@ public function shouldAcceptInvokableObjectCallbackWithUnionTypehint(): void } /** - * @test * @requires PHP 8 */ + #[Test] public function shouldAcceptObjectMethodCallbackWithUnionTypehint(): void { self::assertTrue(_checkTypehint([new CallbackWithUnionTypehintClass(), 'testCallback'], new \InvalidArgumentException())); @@ -97,9 +86,9 @@ public function shouldAcceptObjectMethodCallbackWithUnionTypehint(): void } /** - * @test * @requires PHP 8 */ + #[Test] public function shouldAcceptStaticClassCallbackWithUnionTypehint(): void { self::assertTrue(_checkTypehint([CallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new \InvalidArgumentException())); @@ -107,9 +96,9 @@ public function shouldAcceptStaticClassCallbackWithUnionTypehint(): void } /** - * @test * @requires PHP 8.1 */ + #[Test] public function shouldAcceptInvokableObjectCallbackWithIntersectionTypehint(): void { self::assertFalse(_checkTypehint(new CallbackWithIntersectionTypehintClass(), new \RuntimeException())); @@ -117,9 +106,9 @@ public function shouldAcceptInvokableObjectCallbackWithIntersectionTypehint(): v } /** - * @test * @requires PHP 8.1 */ + #[Test] public function shouldAcceptObjectMethodCallbackWithIntersectionTypehint(): void { self::assertFalse(_checkTypehint([new CallbackWithIntersectionTypehintClass(), 'testCallback'], new \RuntimeException())); @@ -127,9 +116,9 @@ public function shouldAcceptObjectMethodCallbackWithIntersectionTypehint(): void } /** - * @test * @requires PHP 8.1 */ + #[Test] public function shouldAcceptStaticClassCallbackWithIntersectionTypehint(): void { self::assertFalse(_checkTypehint([CallbackWithIntersectionTypehintClass::class, 'testCallbackStatic'], new \RuntimeException())); @@ -137,9 +126,9 @@ public function shouldAcceptStaticClassCallbackWithIntersectionTypehint(): void } /** - * @test * @requires PHP 8.2 */ + #[Test] public function shouldAcceptInvokableObjectCallbackWithDNFTypehint(): void { self::assertFalse(_checkTypehint(new CallbackWithDNFTypehintClass(), new \RuntimeException())); @@ -148,9 +137,9 @@ public function shouldAcceptInvokableObjectCallbackWithDNFTypehint(): void } /** - * @test * @requires PHP 8.2 */ + #[Test] public function shouldAcceptObjectMethodCallbackWithDNFTypehint(): void { self::assertFalse(_checkTypehint([new CallbackWithDNFTypehintClass(), 'testCallback'], new \RuntimeException())); @@ -159,9 +148,9 @@ public function shouldAcceptObjectMethodCallbackWithDNFTypehint(): void } /** - * @test * @requires PHP 8.2 */ + #[Test] public function shouldAcceptStaticClassCallbackWithDNFTypehint(): void { self::assertFalse(_checkTypehint([CallbackWithDNFTypehintClass::class, 'testCallbackStatic'], new \RuntimeException())); @@ -169,41 +158,31 @@ public function shouldAcceptStaticClassCallbackWithDNFTypehint(): void self::assertTrue(_checkTypehint([CallbackWithDNFTypehintClass::class, 'testCallbackStatic'], new IterableException())); } - /** - * @test - */ + #[Test] public function shouldAcceptClosureCallbackWithoutTypehint(): void { self::assertTrue(_checkTypehint(static function (\InvalidArgumentException $e): void {}, new \InvalidArgumentException())); } - /** - * @test - */ + #[Test] public function shouldAcceptFunctionStringCallbackWithoutTypehint(): void { self::assertTrue(_checkTypehint(new CallbackWithoutTypehintClass(), new \InvalidArgumentException())); } - /** - * @test - */ + #[Test] public function shouldAcceptInvokableObjectCallbackWithoutTypehint(): void { self::assertTrue(_checkTypehint(new CallbackWithoutTypehintClass(), new \InvalidArgumentException())); } - /** - * @test - */ + #[Test] public function shouldAcceptObjectMethodCallbackWithoutTypehint(): void { self::assertTrue(_checkTypehint([new CallbackWithoutTypehintClass(), 'testCallback'], new \InvalidArgumentException())); } - /** - * @test - */ + #[Test] public function shouldAcceptStaticClassCallbackWithoutTypehint(): void { self::assertTrue(_checkTypehint([CallbackWithoutTypehintClass::class, 'testCallbackStatic'], new \InvalidArgumentException())); diff --git a/tests/Unit/FunctionRaceTest.php b/tests/Unit/FunctionRaceTest.php index b740fe9..34e0770 100644 --- a/tests/Unit/FunctionRaceTest.php +++ b/tests/Unit/FunctionRaceTest.php @@ -2,8 +2,9 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; +use PHPUnit\Framework\Attributes\Test; use React\Promise\Deferred; use React\Promise\Promise; @@ -11,9 +12,7 @@ class FunctionRaceTest extends TestCase { - /** - * @test - */ + #[Test] public function shouldReturnForeverPendingPromiseForEmptyInput(): void { race( @@ -21,9 +20,7 @@ public function shouldReturnForeverPendingPromiseForEmptyInput(): void )->then($this->expectCallableNever(), $this->expectCallableNever()); } - /** - * @test - */ + #[Test] public function shouldResolveValuesArray(): void { $mock = $this->createCallableMock(); @@ -37,9 +34,7 @@ public function shouldResolveValuesArray(): void )->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolvePromisesArray(): void { $mock = $this->createCallableMock(); @@ -62,9 +57,7 @@ public function shouldResolvePromisesArray(): void $d3->resolve(3); } - /** - * @test - */ + #[Test] public function shouldResolveSparseArrayInput(): void { $mock = $this->createCallableMock(); @@ -78,9 +71,7 @@ public function shouldResolveSparseArrayInput(): void )->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveValuesGenerator(): void { $mock = $this->createCallableMock(); @@ -98,9 +89,7 @@ public function shouldResolveValuesGenerator(): void race($gen)->then($mock); } - /** - * @test - */ + #[Test] public function shouldResolveValuesInfiniteGenerator(): void { $mock = $this->createCallableMock(); @@ -118,9 +107,7 @@ public function shouldResolveValuesInfiniteGenerator(): void race($gen)->then($mock); } - /** - * @test - */ + #[Test] public function shouldRejectIfFirstSettledPromiseRejects(): void { $exception = new \Exception(); @@ -145,9 +132,7 @@ public function shouldRejectIfFirstSettledPromiseRejects(): void $d3->resolve(3); } - /** - * @test - */ + #[Test] public function shouldCancelInputArrayPromises(): void { $promise1 = new Promise(static function (): void {}, $this->expectCallableOnce()); @@ -156,9 +141,7 @@ public function shouldCancelInputArrayPromises(): void race([$promise1, $promise2])->cancel(); } - /** - * @test - */ + #[Test] public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfills(): void { $deferred = new Deferred($this->expectCallableNever()); @@ -169,9 +152,7 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfill race([$deferred->promise(), $promise2])->cancel(); } - /** - * @test - */ + #[Test] public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseRejects(): void { $deferred = new Deferred($this->expectCallableNever()); diff --git a/tests/Unit/FunctionRejectTest.php b/tests/Unit/FunctionRejectTest.php index 9eb5101..d29b8b7 100644 --- a/tests/Unit/FunctionRejectTest.php +++ b/tests/Unit/FunctionRejectTest.php @@ -2,15 +2,15 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; + +use PHPUnit\Framework\Attributes\Test; use function React\Promise\reject; class FunctionRejectTest extends TestCase { - /** - * @test - */ + #[Test] public function shouldRejectAnException(): void { $exception = new \Exception(); diff --git a/tests/Unit/FunctionResolveTest.php b/tests/Unit/FunctionResolveTest.php index 2dd7ce5..cda1003 100644 --- a/tests/Unit/FunctionResolveTest.php +++ b/tests/Unit/FunctionResolveTest.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; -use React\Promise\Unit\Fixture\SimpleFulfilledTestThenable; -use React\Promise\Unit\Fixture\SimpleTestCancellableThenable; +use PHPUnit\Framework\Attributes\Test; +use React\Promise\Tests\Unit\Fixture\SimpleFulfilledTestThenable; +use React\Promise\Tests\Unit\Fixture\SimpleTestCancellableThenable; use React\Promise\Deferred; use React\Promise\Internal\FulfilledPromise; use React\Promise\Internal\RejectedPromise; @@ -14,9 +15,7 @@ class FunctionResolveTest extends TestCase { - /** - * @test - */ + #[Test] public function shouldResolveAnImmediateValue(): void { $expected = 123; @@ -34,9 +33,7 @@ public function shouldResolveAnImmediateValue(): void ); } - /** - * @test - */ + #[Test] public function shouldResolveAFulfilledPromise(): void { $expected = 123; @@ -56,9 +53,7 @@ public function shouldResolveAFulfilledPromise(): void ); } - /** - * @test - */ + #[Test] public function shouldResolveAThenable(): void { $thenable = new SimpleFulfilledTestThenable(); @@ -76,9 +71,7 @@ public function shouldResolveAThenable(): void ); } - /** - * @test - */ + #[Test] public function shouldResolveACancellableThenable(): void { $thenable = new SimpleTestCancellableThenable(); @@ -89,9 +82,7 @@ public function shouldResolveACancellableThenable(): void self::assertTrue($thenable->cancelCalled); } - /** - * @test - */ + #[Test] public function shouldRejectARejectedPromise(): void { $exception = new \Exception(); @@ -111,9 +102,7 @@ public function shouldRejectARejectedPromise(): void ); } - /** - * @test - */ + #[Test] public function shouldSupportDeepNestingInPromiseChains(): void { $d = new Deferred(); @@ -139,9 +128,7 @@ public function shouldSupportDeepNestingInPromiseChains(): void $result->then($mock); } - /** - * @test - */ + #[Test] public function shouldSupportVeryDeepNestedPromises(): void { $deferreds = []; diff --git a/tests/Unit/Internal/CancellationQueueTest.php b/tests/Unit/Internal/CancellationQueueTest.php index a7c73df..2f9eea8 100644 --- a/tests/Unit/Internal/CancellationQueueTest.php +++ b/tests/Unit/Internal/CancellationQueueTest.php @@ -2,19 +2,18 @@ declare(strict_types=1); -namespace React\Promise\Unit\Internal; +namespace React\Promise\Tests\Unit\Internal; +use PHPUnit\Framework\Attributes\Test; use React\Promise\Deferred; use React\Promise\Internal\CancellationQueue; -use React\Promise\Unit\Fixture\SimpleTestCancellable; -use React\Promise\Unit\Fixture\SimpleTestCancellableThenable; -use React\Promise\Unit\TestCase; +use React\Promise\Tests\Unit\Fixture\SimpleTestCancellable; +use React\Promise\Tests\Unit\Fixture\SimpleTestCancellableThenable; +use React\Promise\Tests\Unit\TestCase; class CancellationQueueTest extends TestCase { - /** - * @test - */ + #[Test] public function acceptsSimpleCancellableThenable(): void { $p = new SimpleTestCancellableThenable(); @@ -27,9 +26,7 @@ public function acceptsSimpleCancellableThenable(): void self::assertTrue($p->cancelCalled); } - /** - * @test - */ + #[Test] public function ignoresSimpleCancellable(): void { $p = new SimpleTestCancellable(); @@ -42,9 +39,7 @@ public function ignoresSimpleCancellable(): void self::assertFalse($p->cancelCalled); } - /** - * @test - */ + #[Test] public function callsCancelOnPromisesEnqueuedBeforeStart(): void { $d1 = $this->getCancellableDeferred(); @@ -57,9 +52,7 @@ public function callsCancelOnPromisesEnqueuedBeforeStart(): void $cancellationQueue(); } - /** - * @test - */ + #[Test] public function callsCancelOnPromisesEnqueuedAfterStart(): void { $d1 = $this->getCancellableDeferred(); @@ -73,9 +66,7 @@ public function callsCancelOnPromisesEnqueuedAfterStart(): void $cancellationQueue->enqueue($d1->promise()); } - /** - * @test - */ + #[Test] public function doesNotCallCancelTwiceWhenStartedTwice(): void { $d = $this->getCancellableDeferred(); @@ -87,9 +78,7 @@ public function doesNotCallCancelTwiceWhenStartedTwice(): void $cancellationQueue(); } - /** - * @test - */ + #[Test] public function rethrowsExceptionsThrownFromCancel(): void { $this->expectException(\Exception::class); diff --git a/tests/Unit/Internal/FulfilledPromiseTest.php b/tests/Unit/Internal/FulfilledPromiseTest.php index 2e2c1c3..a9282f9 100644 --- a/tests/Unit/Internal/FulfilledPromiseTest.php +++ b/tests/Unit/Internal/FulfilledPromiseTest.php @@ -2,13 +2,14 @@ declare(strict_types=1); -namespace React\Promise\Unit\Internal; +namespace React\Promise\Tests\Unit\Internal; +use PHPUnit\Framework\Attributes\Test; use React\Promise\Internal\FulfilledPromise; -use React\Promise\Unit\PromiseAdapter\CallbackPromiseAdapter; -use React\Promise\Unit\PromiseTest\PromiseFulfilledTestTrait; -use React\Promise\Unit\PromiseTest\PromiseSettledTestTrait; -use React\Promise\Unit\TestCase; +use React\Promise\Tests\Unit\PromiseAdapter\CallbackPromiseAdapter; +use React\Promise\Tests\Unit\PromiseTest\PromiseFulfilledTestTrait; +use React\Promise\Tests\Unit\PromiseTest\PromiseSettledTestTrait; +use React\Promise\Tests\Unit\TestCase; /** * @template T @@ -50,9 +51,7 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm ]); } - /** - * @test - */ + #[Test] public function shouldThrowExceptionIfConstructedWithAPromise(): void { $this->expectException(\InvalidArgumentException::class); diff --git a/tests/Unit/Internal/RejectedPromiseTest.php b/tests/Unit/Internal/RejectedPromiseTest.php index d0a62c7..ab2117f 100644 --- a/tests/Unit/Internal/RejectedPromiseTest.php +++ b/tests/Unit/Internal/RejectedPromiseTest.php @@ -2,13 +2,13 @@ declare(strict_types=1); -namespace React\Promise\Unit\Internal; +namespace React\Promise\Tests\Unit\Internal; use React\Promise\Internal\RejectedPromise; -use React\Promise\Unit\PromiseAdapter\CallbackPromiseAdapter; -use React\Promise\Unit\PromiseTest\PromiseRejectedTestTrait; -use React\Promise\Unit\PromiseTest\PromiseSettledTestTrait; -use React\Promise\Unit\TestCase; +use React\Promise\Tests\Unit\PromiseAdapter\CallbackPromiseAdapter; +use React\Promise\Tests\Unit\PromiseTest\PromiseRejectedTestTrait; +use React\Promise\Tests\Unit\PromiseTest\PromiseSettledTestTrait; +use React\Promise\Tests\Unit\TestCase; class RejectedPromiseTest extends TestCase { diff --git a/tests/Unit/PromiseAdapter/CallbackPromiseAdapter.php b/tests/Unit/PromiseAdapter/CallbackPromiseAdapter.php index 711f820..10288d0 100644 --- a/tests/Unit/PromiseAdapter/CallbackPromiseAdapter.php +++ b/tests/Unit/PromiseAdapter/CallbackPromiseAdapter.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseAdapter; +namespace React\Promise\Tests\Unit\PromiseAdapter; use React\Promise\PromiseInterface; diff --git a/tests/Unit/PromiseAdapter/PromiseAdapterInterface.php b/tests/Unit/PromiseAdapter/PromiseAdapterInterface.php index 6655c48..0b8ec11 100644 --- a/tests/Unit/PromiseAdapter/PromiseAdapterInterface.php +++ b/tests/Unit/PromiseAdapter/PromiseAdapterInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseAdapter; +namespace React\Promise\Tests\Unit\PromiseAdapter; use React\Promise\PromiseInterface; diff --git a/tests/Unit/PromiseTest.php b/tests/Unit/PromiseTest.php index f8a99bb..aaf92c6 100644 --- a/tests/Unit/PromiseTest.php +++ b/tests/Unit/PromiseTest.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; +use PHPUnit\Framework\Attributes\Test; use React\Promise\Promise; -use React\Promise\Unit\PromiseAdapter\CallbackPromiseAdapter; +use React\Promise\Tests\Unit\PromiseAdapter\CallbackPromiseAdapter; /** * @template T @@ -37,9 +38,7 @@ public function getPromiseTestAdapter(?callable $canceller = null): CallbackProm ]); } - /** - * @test - */ + #[Test] public function shouldRejectIfResolverThrowsException(): void { $exception = new \Exception('foo'); @@ -58,9 +57,7 @@ public function shouldRejectIfResolverThrowsException(): void ->then($this->expectCallableNever(), $mock); } - /** - * @test - */ + #[Test] public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithException(): void { \gc_collect_cycles(); @@ -72,9 +69,7 @@ public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithE $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptionWithoutResolver(): void { \gc_collect_cycles(); @@ -89,9 +84,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithException(): void { \gc_collect_cycles(); @@ -106,9 +99,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithExc $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException(): void { \gc_collect_cycles(); @@ -121,9 +112,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithEx $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException(): void { \gc_collect_cycles(); @@ -136,9 +125,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejects $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsException(): void { \gc_collect_cycles(); @@ -153,9 +140,7 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptio $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise(): void { \gc_collect_cycles(); @@ -165,9 +150,7 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithThenFollowers(): void { \gc_collect_cycles(); @@ -178,9 +161,7 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithCatchFollowers(): void { \gc_collect_cycles(); @@ -191,9 +172,7 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithFinallyFollowers(): void { \gc_collect_cycles(); @@ -205,9 +184,9 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro } /** - * @test * @deprecated */ + #[Test] public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithOtherwiseFollowers(): void { \gc_collect_cycles(); @@ -219,9 +198,9 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro } /** - * @test * @deprecated */ + #[Test] public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithAlwaysFollowers(): void { \gc_collect_cycles(); @@ -232,9 +211,7 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro $this->assertSame(0, \gc_collect_cycles()); } - /** - * @test - */ + #[Test] public function shouldFulfillIfFullfilledWithSimplePromise(): void { \gc_collect_cycles(); diff --git a/tests/Unit/PromiseTest/CancelTestTrait.php b/tests/Unit/PromiseTest/CancelTestTrait.php index 8a582fd..5e12da2 100644 --- a/tests/Unit/PromiseTest/CancelTestTrait.php +++ b/tests/Unit/PromiseTest/CancelTestTrait.php @@ -2,18 +2,17 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseTest; +namespace React\Promise\Tests\Unit\PromiseTest; +use PHPUnit\Framework\Attributes\Test; use React\Promise; -use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; +use React\Promise\Tests\Unit\PromiseAdapter\PromiseAdapterInterface; trait CancelTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** - * @test - */ + #[Test] public function cancelShouldCallCancellerWithResolverArguments(): void { $args = []; @@ -28,9 +27,7 @@ public function cancelShouldCallCancellerWithResolverArguments(): void self::assertTrue(\is_callable($args[1])); } - /** - * @test - */ + #[Test] public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed(): void { $args = null; @@ -43,9 +40,7 @@ public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed(): void self::assertSame(0, $args); } - /** - * @test - */ + #[Test] public function cancelShouldFulfillPromiseIfCancellerFulfills(): void { $adapter = $this->getPromiseTestAdapter(static function ($resolve): void { @@ -64,9 +59,7 @@ public function cancelShouldFulfillPromiseIfCancellerFulfills(): void $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldRejectPromiseIfCancellerRejects(): void { $exception = new \Exception(); @@ -87,9 +80,7 @@ public function cancelShouldRejectPromiseIfCancellerRejects(): void $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldRejectPromiseWithExceptionIfCancellerThrows(): void { $e = new \Exception(); @@ -110,9 +101,7 @@ public function cancelShouldRejectPromiseWithExceptionIfCancellerThrows(): void $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves(): void { $mock = $this->createCallableMock(); @@ -129,9 +118,7 @@ public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves(): void $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldHaveNoEffectIfCancellerDoesNothing(): void { $adapter = $this->getPromiseTestAdapter(static function (): void {}); @@ -143,9 +130,7 @@ public function cancelShouldHaveNoEffectIfCancellerDoesNothing(): void $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldCallCancellerFromDeepNestedPromiseChain(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -162,9 +147,7 @@ public function cancelShouldCallCancellerFromDeepNestedPromiseChain(): void $promise->cancel(); } - /** - * @test - */ + #[Test] public function cancelCalledOnChildrenSouldOnlyCancelWhenAllChildrenCancelled(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -179,9 +162,7 @@ public function cancelCalledOnChildrenSouldOnlyCancelWhenAllChildrenCancelled(): $child1->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldTriggerCancellerWhenAllChildrenCancel(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -197,9 +178,7 @@ public function cancelShouldTriggerCancellerWhenAllChildrenCancel(): void $child2->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldNotTriggerCancellerWhenCancellingOneChildrenMultipleTimes(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -215,9 +194,7 @@ public function cancelShouldNotTriggerCancellerWhenCancellingOneChildrenMultiple $child1->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldTriggerCancellerOnlyOnceWhenCancellingMultipleTimes(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -226,9 +203,7 @@ public function cancelShouldTriggerCancellerOnlyOnceWhenCancellingMultipleTimes( $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldAlwaysTriggerCancellerWhenCalledOnRootPromise(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -243,9 +218,7 @@ public function cancelShouldAlwaysTriggerCancellerWhenCalledOnRootPromise(): voi $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldTriggerCancellerWhenFollowerCancels(): void { $adapter1 = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -260,9 +233,7 @@ public function cancelShouldTriggerCancellerWhenFollowerCancels(): void $follower->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldNotTriggerCancellerWhenCancellingOnlyOneFollower(): void { $adapter1 = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -280,9 +251,7 @@ public function cancelShouldNotTriggerCancellerWhenCancellingOnlyOneFollower(): $follower1->cancel(); } - /** - * @test - */ + #[Test] public function cancelCalledOnFollowerShouldOnlyCancelWhenAllChildrenAndFollowerCancelled(): void { $adapter1 = $this->getPromiseTestAdapter($this->expectCallableOnce()); @@ -300,9 +269,7 @@ public function cancelCalledOnFollowerShouldOnlyCancelWhenAllChildrenAndFollower $child->cancel(); } - /** - * @test - */ + #[Test] public function cancelShouldNotTriggerCancellerWhenCancellingFollowerButNotChildren(): void { $adapter1 = $this->getPromiseTestAdapter($this->expectCallableNever()); diff --git a/tests/Unit/PromiseTest/FullTestTrait.php b/tests/Unit/PromiseTest/FullTestTrait.php index 83391d0..bddc733 100644 --- a/tests/Unit/PromiseTest/FullTestTrait.php +++ b/tests/Unit/PromiseTest/FullTestTrait.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseTest; +namespace React\Promise\Tests\Unit\PromiseTest; trait FullTestTrait { diff --git a/tests/Unit/PromiseTest/PromiseFulfilledTestTrait.php b/tests/Unit/PromiseTest/PromiseFulfilledTestTrait.php index b931a79..ae663b7 100644 --- a/tests/Unit/PromiseTest/PromiseFulfilledTestTrait.php +++ b/tests/Unit/PromiseTest/PromiseFulfilledTestTrait.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseTest; +namespace React\Promise\Tests\Unit\PromiseTest; +use PHPUnit\Framework\Attributes\Test; use React\Promise\PromiseInterface; -use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; +use React\Promise\Tests\Unit\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; @@ -14,9 +15,7 @@ trait PromiseFulfilledTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** - * @test - */ + #[Test] public function fulfilledPromiseShouldBeImmutable(): void { $adapter = $this->getPromiseTestAdapter(); @@ -37,9 +36,7 @@ public function fulfilledPromiseShouldBeImmutable(): void ); } - /** - * @test - */ + #[Test] public function fulfilledPromiseShouldInvokeNewlyAddedCallback(): void { $adapter = $this->getPromiseTestAdapter(); @@ -56,9 +53,7 @@ public function fulfilledPromiseShouldInvokeNewlyAddedCallback(): void ->then($mock, $this->expectCallableNever()); } - /** - * @test - */ + #[Test] public function thenShouldForwardResultWhenCallbackIsNull(): void { $adapter = $this->getPromiseTestAdapter(); @@ -81,9 +76,7 @@ public function thenShouldForwardResultWhenCallbackIsNull(): void ); } - /** - * @test - */ + #[Test] public function thenShouldForwardCallbackResultToNextCallback(): void { $adapter = $this->getPromiseTestAdapter(); @@ -106,9 +99,7 @@ public function thenShouldForwardCallbackResultToNextCallback(): void ); } - /** - * @test - */ + #[Test] public function thenShouldForwardPromisedCallbackResultValueToNextCallback(): void { $adapter = $this->getPromiseTestAdapter(); @@ -131,9 +122,7 @@ public function thenShouldForwardPromisedCallbackResultValueToNextCallback(): vo ); } - /** - * @test - */ + #[Test] public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackReturnsARejection(): void { $adapter = $this->getPromiseTestAdapter(); @@ -158,9 +147,7 @@ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackReturnsARejec ); } - /** - * @test - */ + #[Test] public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackThrows(): void { $adapter = $this->getPromiseTestAdapter(); @@ -192,9 +179,9 @@ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackThrows(): voi } /** - * @test * @requires PHP 8.1 */ + #[Test] public function thenShouldContinueToExecuteCallbacksWhenPriorCallbackSuspendsFiber(): void { /** @var PromiseAdapterInterface $adapter */ @@ -219,9 +206,7 @@ public function thenShouldContinueToExecuteCallbacksWhenPriorCallbackSuspendsFib $adapter->promise()->then($mock); } - /** - * @test - */ + #[Test] public function cancelShouldHaveNoEffectForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -231,9 +216,7 @@ public function cancelShouldHaveNoEffectForFulfilledPromise(): void $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function catchShouldNotInvokeRejectionHandlerForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -242,9 +225,7 @@ public function catchShouldNotInvokeRejectionHandlerForFulfilledPromise(): void $adapter->promise()->catch($this->expectCallableNever()); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressValueForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -263,9 +244,7 @@ public function finallyShouldNotSuppressValueForFulfilledPromise(): void ->then($mock); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -285,9 +264,7 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFul ->then($mock); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -307,9 +284,7 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfil ->then($mock); } - /** - * @test - */ + #[Test] public function finallyShouldRejectWhenHandlerThrowsForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -330,9 +305,7 @@ public function finallyShouldRejectWhenHandlerThrowsForFulfilledPromise(): void ->then(null, $mock); } - /** - * @test - */ + #[Test] public function finallyShouldRejectWhenHandlerRejectsForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -352,9 +325,9 @@ public function finallyShouldRejectWhenHandlerRejectsForFulfilledPromise(): void } /** - * @test * @deprecated */ + #[Test] public function otherwiseShouldNotInvokeRejectionHandlerForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -364,9 +337,9 @@ public function otherwiseShouldNotInvokeRejectionHandlerForFulfilledPromise(): v } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldNotSuppressValueForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -386,9 +359,9 @@ public function alwaysShouldNotSuppressValueForFulfilledPromise(): void } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -409,9 +382,9 @@ public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulf } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -432,9 +405,9 @@ public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfill } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldRejectWhenHandlerThrowsForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -456,9 +429,9 @@ public function alwaysShouldRejectWhenHandlerThrowsForFulfilledPromise(): void } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldRejectWhenHandlerRejectsForFulfilledPromise(): void { $adapter = $this->getPromiseTestAdapter(); diff --git a/tests/Unit/PromiseTest/PromisePendingTestTrait.php b/tests/Unit/PromiseTest/PromisePendingTestTrait.php index 8f8e4c2..dfd1680 100644 --- a/tests/Unit/PromiseTest/PromisePendingTestTrait.php +++ b/tests/Unit/PromiseTest/PromisePendingTestTrait.php @@ -2,18 +2,17 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseTest; +namespace React\Promise\Tests\Unit\PromiseTest; +use PHPUnit\Framework\Attributes\Test; use React\Promise\PromiseInterface; -use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; +use React\Promise\Tests\Unit\PromiseAdapter\PromiseAdapterInterface; trait PromisePendingTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** - * @test - */ + #[Test] public function thenShouldReturnAPromiseForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -21,9 +20,7 @@ public function thenShouldReturnAPromiseForPendingPromise(): void self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->then()); } - /** - * @test - */ + #[Test] public function thenShouldReturnAllowNullForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -31,9 +28,7 @@ public function thenShouldReturnAllowNullForPendingPromise(): void self::assertInstanceOf(PromiseInterface::class, $adapter->promise()->then(null, null)); } - /** - * @test - */ + #[Test] public function catchShouldNotInvokeRejectionHandlerForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -42,9 +37,7 @@ public function catchShouldNotInvokeRejectionHandlerForPendingPromise(): void $adapter->promise()->catch($this->expectCallableNever()); } - /** - * @test - */ + #[Test] public function finallyShouldReturnAPromiseForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -53,9 +46,9 @@ public function finallyShouldReturnAPromiseForPendingPromise(): void } /** - * @test * @deprecated */ + #[Test] public function otherwiseShouldNotInvokeRejectionHandlerForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -65,9 +58,9 @@ public function otherwiseShouldNotInvokeRejectionHandlerForPendingPromise(): voi } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldReturnAPromiseForPendingPromise(): void { $adapter = $this->getPromiseTestAdapter(); diff --git a/tests/Unit/PromiseTest/PromiseRejectedTestTrait.php b/tests/Unit/PromiseTest/PromiseRejectedTestTrait.php index 102b909..ee8f887 100644 --- a/tests/Unit/PromiseTest/PromiseRejectedTestTrait.php +++ b/tests/Unit/PromiseTest/PromiseRejectedTestTrait.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseTest; +namespace React\Promise\Tests\Unit\PromiseTest; +use PHPUnit\Framework\Attributes\Test; use React\Promise\PromiseInterface; -use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; +use React\Promise\Tests\Unit\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; @@ -14,9 +15,7 @@ trait PromiseRejectedTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** - * @test - */ + #[Test] public function rejectedPromiseShouldBeImmutable(): void { $adapter = $this->getPromiseTestAdapter(); @@ -40,9 +39,7 @@ public function rejectedPromiseShouldBeImmutable(): void ); } - /** - * @test - */ + #[Test] public function rejectedPromiseShouldInvokeNewlyAddedCallback(): void { $adapter = $this->getPromiseTestAdapter(); @@ -61,9 +58,7 @@ public function rejectedPromiseShouldInvokeNewlyAddedCallback(): void ->then($this->expectCallableNever(), $mock); } - /** - * @test - */ + #[Test] public function shouldForwardUndefinedRejectionValue(): void { $adapter = $this->getPromiseTestAdapter(); @@ -91,9 +86,7 @@ static function (): void { ); } - /** - * @test - */ + #[Test] public function shouldSwitchFromErrbacksToCallbacksWhenErrbackDoesNotExplicitlyPropagate(): void { $adapter = $this->getPromiseTestAdapter(); @@ -116,9 +109,7 @@ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackDoesNotExplicitlyP ); } - /** - * @test - */ + #[Test] public function shouldSwitchFromErrbacksToCallbacksWhenErrbackReturnsAResolution(): void { $adapter = $this->getPromiseTestAdapter(); @@ -141,9 +132,7 @@ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackReturnsAResolution ); } - /** - * @test - */ + #[Test] public function shouldPropagateRejectionsWhenErrbackThrows(): void { $adapter = $this->getPromiseTestAdapter(); @@ -174,9 +163,7 @@ public function shouldPropagateRejectionsWhenErrbackThrows(): void ); } - /** - * @test - */ + #[Test] public function shouldPropagateRejectionsWhenErrbackReturnsARejection(): void { $adapter = $this->getPromiseTestAdapter(); @@ -201,9 +188,7 @@ public function shouldPropagateRejectionsWhenErrbackReturnsARejection(): void ); } - /** - * @test - */ + #[Test] public function catchShouldInvokeRejectionHandlerForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -220,9 +205,7 @@ public function catchShouldInvokeRejectionHandlerForRejectedPromise(): void $adapter->promise()->catch($mock); } - /** - * @test - */ + #[Test] public function catchShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExceptionForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -242,9 +225,7 @@ public function catchShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExcept }); } - /** - * @test - */ + #[Test] public function catchShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -264,9 +245,7 @@ public function catchShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejec }); } - /** - * @test - */ + #[Test] public function catchShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchTypehintForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -282,9 +261,7 @@ public function catchShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchTypehint })->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressRejectionForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -303,9 +280,7 @@ public function finallyShouldNotSuppressRejectionForRejectedPromise(): void ->then(null, $mock); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -326,9 +301,7 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseFo ->then(null, $mock); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -349,9 +322,7 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRe ->then(null, $mock); } - /** - * @test - */ + #[Test] public function finallyShouldRejectWhenHandlerThrowsForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -373,9 +344,7 @@ public function finallyShouldRejectWhenHandlerThrowsForRejectedPromise(): void ->then(null, $mock); } - /** - * @test - */ + #[Test] public function finallyShouldRejectWhenHandlerRejectsForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -395,9 +364,7 @@ public function finallyShouldRejectWhenHandlerRejectsForRejectedPromise(): void ->then(null, $mock); } - /** - * @test - */ + #[Test] public function cancelShouldHaveNoEffectForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -408,9 +375,9 @@ public function cancelShouldHaveNoEffectForRejectedPromise(): void } /** - * @test * @deprecated */ + #[Test] public function otherwiseShouldInvokeRejectionHandlerForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -428,9 +395,9 @@ public function otherwiseShouldInvokeRejectionHandlerForRejectedPromise(): void } /** - * @test * @deprecated */ + #[Test] public function otherwiseShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExceptionForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -451,9 +418,9 @@ public function otherwiseShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnEx } /** - * @test * @deprecated */ + #[Test] public function otherwiseShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -474,9 +441,9 @@ public function otherwiseShouldInvokeRejectionHandlerIfReasonMatchesTypehintForR } /** - * @test * @deprecated */ + #[Test] public function otherwiseShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchTypehintForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -493,9 +460,9 @@ public function otherwiseShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchType } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldNotSuppressRejectionForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -515,9 +482,9 @@ public function alwaysShouldNotSuppressRejectionForRejectedPromise(): void } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -539,9 +506,9 @@ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseFor } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -563,9 +530,9 @@ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRej } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldRejectWhenHandlerThrowsForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -588,9 +555,9 @@ public function alwaysShouldRejectWhenHandlerThrowsForRejectedPromise(): void } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldRejectWhenHandlerRejectsForRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); diff --git a/tests/Unit/PromiseTest/PromiseSettledTestTrait.php b/tests/Unit/PromiseTest/PromiseSettledTestTrait.php index 375cf58..8699fdf 100644 --- a/tests/Unit/PromiseTest/PromiseSettledTestTrait.php +++ b/tests/Unit/PromiseTest/PromiseSettledTestTrait.php @@ -2,19 +2,18 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseTest; +namespace React\Promise\Tests\Unit\PromiseTest; +use PHPUnit\Framework\Attributes\Test; use React\Promise\Internal\RejectedPromise; use React\Promise\PromiseInterface; -use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; +use React\Promise\Tests\Unit\PromiseAdapter\PromiseAdapterInterface; trait PromiseSettledTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** - * @test - */ + #[Test] public function thenShouldReturnAPromiseForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -27,9 +26,7 @@ public function thenShouldReturnAPromiseForSettledPromise(): void } } - /** - * @test - */ + #[Test] public function thenShouldReturnAllowNullForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -42,9 +39,7 @@ public function thenShouldReturnAllowNullForSettledPromise(): void } } - /** - * @test - */ + #[Test] public function cancelShouldHaveNoEffectForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); @@ -54,9 +49,7 @@ public function cancelShouldHaveNoEffectForSettledPromise(): void $adapter->promise()->cancel(); } - /** - * @test - */ + #[Test] public function finallyShouldReturnAPromiseForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -70,9 +63,9 @@ public function finallyShouldReturnAPromiseForSettledPromise(): void } /** - * @test * @deprecated */ + #[Test] public function alwaysShouldReturnAPromiseForSettledPromise(): void { $adapter = $this->getPromiseTestAdapter(); diff --git a/tests/Unit/PromiseTest/RejectTestTrait.php b/tests/Unit/PromiseTest/RejectTestTrait.php index ce0958e..4451508 100644 --- a/tests/Unit/PromiseTest/RejectTestTrait.php +++ b/tests/Unit/PromiseTest/RejectTestTrait.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseTest; +namespace React\Promise\Tests\Unit\PromiseTest; +use PHPUnit\Framework\Attributes\Test; use React\Promise\PromiseInterface; -use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; +use React\Promise\Tests\Unit\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; @@ -14,9 +15,7 @@ trait RejectTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** - * @test - */ + #[Test] public function rejectShouldRejectWithAnException(): void { $adapter = $this->getPromiseTestAdapter(); @@ -35,9 +34,7 @@ public function rejectShouldRejectWithAnException(): void $adapter->reject($exception); } - /** - * @test - */ + #[Test] public function rejectShouldForwardReasonWhenCallbackIsNull(): void { $adapter = $this->getPromiseTestAdapter(); @@ -62,9 +59,7 @@ public function rejectShouldForwardReasonWhenCallbackIsNull(): void $adapter->reject($exception); } - /** - * @test - */ + #[Test] public function rejectShouldMakePromiseImmutable(): void { $adapter = $this->getPromiseTestAdapter(); @@ -94,9 +89,7 @@ public function rejectShouldMakePromiseImmutable(): void $adapter->reject($exception2); } - /** - * @test - */ + #[Test] public function rejectShouldInvokeCatchHandler(): void { $adapter = $this->getPromiseTestAdapter(); @@ -115,9 +108,7 @@ public function rejectShouldInvokeCatchHandler(): void $adapter->reject($exception); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressRejection(): void { $adapter = $this->getPromiseTestAdapter(); @@ -137,9 +128,7 @@ public function finallyShouldNotSuppressRejection(): void $adapter->reject($exception); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -160,9 +149,7 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsANonPromise() $adapter->reject($exception); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -183,9 +170,7 @@ public function finallyShouldNotSuppressRejectionWhenHandlerReturnsAPromise(): v $adapter->reject($exception); } - /** - * @test - */ + #[Test] public function finallyShouldRejectWhenHandlerThrowsForRejection(): void { $adapter = $this->getPromiseTestAdapter(); @@ -207,9 +192,7 @@ public function finallyShouldRejectWhenHandlerThrowsForRejection(): void $adapter->reject($exception); } - /** - * @test - */ + #[Test] public function finallyShouldRejectWhenHandlerRejectsForRejection(): void { $adapter = $this->getPromiseTestAdapter(); diff --git a/tests/Unit/PromiseTest/ResolveTestTrait.php b/tests/Unit/PromiseTest/ResolveTestTrait.php index 6a7e76d..6594365 100644 --- a/tests/Unit/PromiseTest/ResolveTestTrait.php +++ b/tests/Unit/PromiseTest/ResolveTestTrait.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace React\Promise\Unit\PromiseTest; +namespace React\Promise\Tests\Unit\PromiseTest; +use PHPUnit\Framework\Attributes\Test; use React\Promise\PromiseInterface; -use React\Promise\Unit\PromiseAdapter\PromiseAdapterInterface; +use React\Promise\Tests\Unit\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; @@ -14,9 +15,7 @@ trait ResolveTestTrait { abstract public function getPromiseTestAdapter(?callable $canceller = null): PromiseAdapterInterface; - /** - * @test - */ + #[Test] public function resolveShouldResolve(): void { $adapter = $this->getPromiseTestAdapter(); @@ -33,9 +32,7 @@ public function resolveShouldResolve(): void $adapter->resolve(1); } - /** - * @test - */ + #[Test] public function resolveShouldResolveWithPromisedValue(): void { $adapter = $this->getPromiseTestAdapter(); @@ -52,9 +49,7 @@ public function resolveShouldResolveWithPromisedValue(): void $adapter->resolve(resolve(1)); } - /** - * @test - */ + #[Test] public function resolveShouldRejectWhenResolvedWithRejectedPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -73,9 +68,7 @@ public function resolveShouldRejectWhenResolvedWithRejectedPromise(): void $adapter->resolve(reject($exception)); } - /** - * @test - */ + #[Test] public function resolveShouldForwardValueWhenCallbackIsNull(): void { $adapter = $this->getPromiseTestAdapter(); @@ -99,9 +92,7 @@ public function resolveShouldForwardValueWhenCallbackIsNull(): void $adapter->resolve(1); } - /** - * @test - */ + #[Test] public function resolveShouldMakePromiseImmutable(): void { $adapter = $this->getPromiseTestAdapter(); @@ -127,9 +118,7 @@ public function resolveShouldMakePromiseImmutable(): void $adapter->resolve(2); } - /** - * @test - */ + #[Test] public function resolveShouldRejectWhenResolvedWithItself(): void { $adapter = $this->getPromiseTestAdapter(); @@ -149,9 +138,7 @@ public function resolveShouldRejectWhenResolvedWithItself(): void $adapter->resolve($adapter->promise()); } - /** - * @test - */ + #[Test] public function resolveShouldRejectWhenResolvedWithAPromiseWhichFollowsItself(): void { $adapter1 = $this->getPromiseTestAdapter(); @@ -176,9 +163,7 @@ public function resolveShouldRejectWhenResolvedWithAPromiseWhichFollowsItself(): $adapter2->resolve($promise1); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressValue(): void { $adapter = $this->getPromiseTestAdapter(); @@ -198,9 +183,7 @@ public function finallyShouldNotSuppressValue(): void $adapter->resolve($value); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -221,9 +204,7 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromise(): vo $adapter->resolve($value); } - /** - * @test - */ + #[Test] public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromise(): void { $adapter = $this->getPromiseTestAdapter(); @@ -245,9 +226,7 @@ public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromise(): void $adapter->resolve($value); } - /** - * @test - */ + #[Test] public function finallyShouldRejectWhenHandlerThrowsForFulfillment(): void { $adapter = $this->getPromiseTestAdapter(); @@ -269,9 +248,7 @@ public function finallyShouldRejectWhenHandlerThrowsForFulfillment(): void $adapter->resolve(1); } - /** - * @test - */ + #[Test] public function finallyShouldRejectWhenHandlerRejectsForFulfillment(): void { $adapter = $this->getPromiseTestAdapter(); diff --git a/tests/Unit/TestCase.php b/tests/Unit/TestCase.php index 31965c2..1542d98 100644 --- a/tests/Unit/TestCase.php +++ b/tests/Unit/TestCase.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace React\Promise\Unit; +namespace React\Promise\Tests\Unit; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase as BaseTestCase; @@ -47,7 +47,7 @@ protected function createCallableMock(): MockObject $mock = $builder->addMethods(['__invoke'])->getMock(); } else { // legacy PHPUnit 4 - PHPUnit 9 - $mock = $builder->setMethods(['__invoke'])->getMock(); + $mock = $builder->getMock(); } \assert($mock instanceof MockObject && \is_callable($mock)); From 099a049a73403f54b8026eb9d29c130e4ae93ed7 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 17:46:24 +0400 Subject: [PATCH 17/18] ci: Run cases separately --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eea15d5..d495381 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,9 @@ jobs: coverage: xdebug ini-file: development - run: composer install - - run: composer test:cc + - run: composer test:arch + - run: composer test:unit + - run: composer test:feat PHPStan: name: PHPStan (PHP ${{ matrix.php }}) From b68b528e5b92c671bf8104cc3c4dfc1f94c16e5f Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 27 Aug 2025 17:55:57 +0400 Subject: [PATCH 18/18] chore: Update .gitattributes and .gitignore; add .editorconfig --- .editorconfig | 21 +++++++++++++++++++++ .gitattributes | 2 +- .gitignore | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..20d4cdf --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.yaml] +indent_size = 2 + +[*.yml] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/.gitattributes b/.gitattributes index 7104267..c466442 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ -* text=auto +* text=auto eol=lf /.* export-ignore /tests export-ignore diff --git a/.gitignore b/.gitignore index 99dd26d..7c97d91 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /.* !/.github/ !/.php-cs-fixer.dist.php +!/.editorconfig /runtime/ /vendor/ /.env