From f8ad2e6bf8f92a82d0781c7b2de62cbb37739e60 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 21 Feb 2023 16:32:48 -0600 Subject: [PATCH 1/8] feat: update to v2 usage of PSR-7 Refactors tests that were using the assumption of throwing an `InvalidArgumentException` to test for either `InvalidArgumentException` OR `TypeError`. This change will allow testing against PSR-7 1.1+ releases safely. --- composer.json | 4 ++-- src/MessageTrait.php | 36 +++++++++++++++++++++++++++------ src/RequestIntegrationTest.php | 16 +++++++++++++-- src/ResponseIntegrationTest.php | 16 +++++++++++++-- src/UriIntegrationTest.php | 16 +++++++++++++-- 5 files changed, 74 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index 7ca39e0..8089536 100644 --- a/composer.json +++ b/composer.json @@ -16,14 +16,14 @@ "require": { "php": "^7.2 || ^8.0", "phpunit/phpunit": "^8.0 || ^9.3", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "require-dev": { "guzzlehttp/psr7": "^1.7 || ^2.0", "laminas/laminas-diactoros": "^2.1", "nyholm/psr7": "^1.0", "ringcentral/psr7": "^1.2", - "slim/psr7": "dev-master" + "slim/psr7": "^1.4" }, "extra": { "branch-alias": { diff --git a/src/MessageTrait.php b/src/MessageTrait.php index 5b30d16..bddbece 100644 --- a/src/MessageTrait.php +++ b/src/MessageTrait.php @@ -2,7 +2,10 @@ namespace Http\Psr7Test; +use InvalidArgumentException; use Psr\Http\Message\MessageInterface; +use Throwable; +use TypeError; /** * Test MessageInterface. @@ -136,9 +139,19 @@ public function testWithHeaderInvalidArguments($name, $value) if (isset($this->skippedTests[__FUNCTION__])) { $this->markTestSkipped($this->skippedTests[__FUNCTION__]); } - $this->expectException(\InvalidArgumentException::class); - $initialMessage = $this->getMessage(); - $initialMessage->withHeader($name, $value); + + try { + $initialMessage = $this->getMessage(); + $initialMessage->withHeader($name, $value); + } catch (TypeError|InvalidArgumentException $e) { + // valid + } catch (Throwable $e) { + // invalid + $this->fail(sprintf( + 'Unexpected exception (%s) thrown from withHeader(); expected TypeError or InvalidArgumentException', + gettype($e) + )); + } } public function getInvalidHeaderArguments() @@ -154,6 +167,7 @@ public function getInvalidHeaderArguments() ]; } + public function testWithAddedHeader() { if (isset($this->skippedTests[__FUNCTION__])) { @@ -174,9 +188,19 @@ public function testWithAddedHeaderInvalidArguments($name, $value) if (isset($this->skippedTests[__FUNCTION__])) { $this->markTestSkipped($this->skippedTests[__FUNCTION__]); } - $this->expectException(\InvalidArgumentException::class); - $initialMessage = $this->getMessage(); - $initialMessage->withAddedHeader($name, $value); + + try { + $initialMessage = $this->getMessage(); + $initialMessage->withAddedHeader($name, $value); + } catch (TypeError|InvalidArgumentException $e) { + // valid + } catch (Throwable $e) { + // invalid + $this->fail(sprintf( + 'Unexpected exception (%s) thrown from withAddedHeader(); expected TypeError or InvalidArgumentException', + gettype($e) + )); + } } /** diff --git a/src/RequestIntegrationTest.php b/src/RequestIntegrationTest.php index 5b6d6a5..2a9a9fd 100644 --- a/src/RequestIntegrationTest.php +++ b/src/RequestIntegrationTest.php @@ -2,8 +2,11 @@ namespace Http\Psr7Test; +use InvalidArgumentException; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; +use Throwable; +use TypeError; /** * @author Tobias Nyholm @@ -96,8 +99,17 @@ public function testMethodWithInvalidArguments($method) $this->markTestSkipped($this->skippedTests[__FUNCTION__]); } - $this->expectException(\InvalidArgumentException::class); - $this->request->withMethod($method); + try { + $this->request->withMethod($method); + } catch (InvalidArgumentException|TypeError $e) { + // valid + } catch (Throwable $e) { + // invalid + $this->fail(sprintf( + 'Unexpected exception (%s) thrown from withMethod(); expected TypeError or InvalidArgumentException', + gettype($e) + )); + } } public function getInvalidMethods() diff --git a/src/ResponseIntegrationTest.php b/src/ResponseIntegrationTest.php index 9abd790..ead90fb 100644 --- a/src/ResponseIntegrationTest.php +++ b/src/ResponseIntegrationTest.php @@ -2,7 +2,10 @@ namespace Http\Psr7Test; +use InvalidArgumentException; use Psr\Http\Message\ResponseInterface; +use Throwable; +use TypeError; /** * @author Tobias Nyholm @@ -58,8 +61,17 @@ public function testStatusCodeInvalidArgument($statusCode) $this->markTestSkipped($this->skippedTests[__FUNCTION__]); } - $this->expectException(\InvalidArgumentException::class); - $this->response->withStatus($statusCode); + try { + $this->response->withStatus($statusCode); + } catch (InvalidArgumentException|TypeError $e) { + // valid + } catch (Throwable $e) { + // invalid + $this->fail(sprintf( + 'Unexpected exception (%s) thrown from withStatus(); expected TypeError or InvalidArgumentException', + gettype($e) + )); + } } public function getInvalidStatusCodeArguments() diff --git a/src/UriIntegrationTest.php b/src/UriIntegrationTest.php index c1181cf..325ea68 100644 --- a/src/UriIntegrationTest.php +++ b/src/UriIntegrationTest.php @@ -2,7 +2,10 @@ namespace Http\Psr7Test; +use InvalidArgumentException; use Psr\Http\Message\UriInterface; +use Throwable; +use TypeError; /** * @author Tobias Nyholm @@ -47,8 +50,17 @@ public function testWithSchemeInvalidArguments($schema) $this->markTestSkipped($this->skippedTests[__FUNCTION__]); } - $this->expectException(\InvalidArgumentException::class); - $this->createUri('/')->withScheme($schema); + try { + $this->createUri('/')->withScheme($schema); + } catch (InvalidArgumentException|TypeError $e) { + // valid + } catch (Throwable $e) { + // invalid + $this->fail(sprintf( + 'Unexpected exception (%s) thrown from withScheme(); expected TypeError or InvalidArgumentException', + gettype($e) + )); + } } public function getInvalidSchemaArguments() From 6ed8ec16fcd7c6696bc8dfdf026c2c2baaab3f03 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 4 Apr 2023 15:03:21 -0500 Subject: [PATCH 2/8] qa: remove extra linebreak --- src/MessageTrait.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/MessageTrait.php b/src/MessageTrait.php index bddbece..a2f1c36 100644 --- a/src/MessageTrait.php +++ b/src/MessageTrait.php @@ -167,7 +167,6 @@ public function getInvalidHeaderArguments() ]; } - public function testWithAddedHeader() { if (isset($this->skippedTests[__FUNCTION__])) { From 81b8c881b8ba7565458b150f47878bf1d6e3eeba Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 4 Apr 2023 15:05:03 -0500 Subject: [PATCH 3/8] docs: provides a CHANGELOG entry for #68 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1985596..c579e87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 These validate that usernames and passwords which contain reserved characters (defined by RFC3986) are being encoded so that the URI does not contain these reserved characters at any time. +- Adds support for testing against PSR-7 1.1 and 2.0. In particular, it adapts tests that were verifying invalid parameters threw `InvalidArgumentException` previously now either throw that OR (more correctly) raise a `TypeError`. + ## [1.2.0] - 2022-12-01 ### Added From c45f07d6858bca1d36f6f8bee1bfdf74374a6584 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 4 Apr 2023 15:53:09 -0500 Subject: [PATCH 4/8] fix: always assert When performing try/catch blocks, and the catch represents a valid condition, we need to assert SOMETHING, or else the test is flagged as risky. A simple assertion that we got a throwable works in these cases. --- src/MessageTrait.php | 2 ++ src/RequestIntegrationTest.php | 1 + src/ResponseIntegrationTest.php | 1 + src/UriIntegrationTest.php | 1 + 4 files changed, 5 insertions(+) diff --git a/src/MessageTrait.php b/src/MessageTrait.php index a2f1c36..e4dcf49 100644 --- a/src/MessageTrait.php +++ b/src/MessageTrait.php @@ -145,6 +145,7 @@ public function testWithHeaderInvalidArguments($name, $value) $initialMessage->withHeader($name, $value); } catch (TypeError|InvalidArgumentException $e) { // valid + $this->assertTrue($e instanceof Throwable); } catch (Throwable $e) { // invalid $this->fail(sprintf( @@ -193,6 +194,7 @@ public function testWithAddedHeaderInvalidArguments($name, $value) $initialMessage->withAddedHeader($name, $value); } catch (TypeError|InvalidArgumentException $e) { // valid + $this->assertTrue($e instanceof Throwable); } catch (Throwable $e) { // invalid $this->fail(sprintf( diff --git a/src/RequestIntegrationTest.php b/src/RequestIntegrationTest.php index 2a9a9fd..3bef090 100644 --- a/src/RequestIntegrationTest.php +++ b/src/RequestIntegrationTest.php @@ -103,6 +103,7 @@ public function testMethodWithInvalidArguments($method) $this->request->withMethod($method); } catch (InvalidArgumentException|TypeError $e) { // valid + $this->assertTrue($e instanceof Throwable); } catch (Throwable $e) { // invalid $this->fail(sprintf( diff --git a/src/ResponseIntegrationTest.php b/src/ResponseIntegrationTest.php index ead90fb..d0063e0 100644 --- a/src/ResponseIntegrationTest.php +++ b/src/ResponseIntegrationTest.php @@ -65,6 +65,7 @@ public function testStatusCodeInvalidArgument($statusCode) $this->response->withStatus($statusCode); } catch (InvalidArgumentException|TypeError $e) { // valid + $this->assertTrue($e instanceof Throwable); } catch (Throwable $e) { // invalid $this->fail(sprintf( diff --git a/src/UriIntegrationTest.php b/src/UriIntegrationTest.php index 325ea68..205d1f9 100644 --- a/src/UriIntegrationTest.php +++ b/src/UriIntegrationTest.php @@ -54,6 +54,7 @@ public function testWithSchemeInvalidArguments($schema) $this->createUri('/')->withScheme($schema); } catch (InvalidArgumentException|TypeError $e) { // valid + $this->assertTrue($e instanceof Throwable); } catch (Throwable $e) { // invalid $this->fail(sprintf( From 545f2943e85600013ea546df0585e27c41bab179 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Tue, 4 Apr 2023 16:03:17 -0500 Subject: [PATCH 5/8] fix: ensure invalid arguments not caught by implementation are flagged Adds a `fail()` call when an invalid argument is not caught. --- src/MessageTrait.php | 9 +++++++++ src/RequestIntegrationTest.php | 5 +++++ src/ResponseIntegrationTest.php | 5 +++++ src/UriIntegrationTest.php | 5 +++++ 4 files changed, 24 insertions(+) diff --git a/src/MessageTrait.php b/src/MessageTrait.php index e4dcf49..c21bbc9 100644 --- a/src/MessageTrait.php +++ b/src/MessageTrait.php @@ -3,6 +3,7 @@ namespace Http\Psr7Test; use InvalidArgumentException; +use PHPUnit\Framework\AssertionFailedError; use Psr\Http\Message\MessageInterface; use Throwable; use TypeError; @@ -143,6 +144,10 @@ public function testWithHeaderInvalidArguments($name, $value) try { $initialMessage = $this->getMessage(); $initialMessage->withHeader($name, $value); + $this->fail('withHeader() should have raised exception on invalid argument'); + } catch (AssertionFailedError $e) { + // invalid argument not caught + throw $e; } catch (TypeError|InvalidArgumentException $e) { // valid $this->assertTrue($e instanceof Throwable); @@ -192,6 +197,10 @@ public function testWithAddedHeaderInvalidArguments($name, $value) try { $initialMessage = $this->getMessage(); $initialMessage->withAddedHeader($name, $value); + $this->fail('withAddedHeader() should have raised exception on invalid argument'); + } catch (AssertionFailedError $e) { + // invalid argument not caught + throw $e; } catch (TypeError|InvalidArgumentException $e) { // valid $this->assertTrue($e instanceof Throwable); diff --git a/src/RequestIntegrationTest.php b/src/RequestIntegrationTest.php index 3bef090..f466bb4 100644 --- a/src/RequestIntegrationTest.php +++ b/src/RequestIntegrationTest.php @@ -3,6 +3,7 @@ namespace Http\Psr7Test; use InvalidArgumentException; +use PHPUnit\Framework\AssertionFailedError; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; use Throwable; @@ -101,6 +102,10 @@ public function testMethodWithInvalidArguments($method) try { $this->request->withMethod($method); + $this->fail('withMethod() should have raised exception on invalid argument'); + } catch (AssertionFailedError $e) { + // invalid argument not caught + throw $e; } catch (InvalidArgumentException|TypeError $e) { // valid $this->assertTrue($e instanceof Throwable); diff --git a/src/ResponseIntegrationTest.php b/src/ResponseIntegrationTest.php index d0063e0..d2ee924 100644 --- a/src/ResponseIntegrationTest.php +++ b/src/ResponseIntegrationTest.php @@ -3,6 +3,7 @@ namespace Http\Psr7Test; use InvalidArgumentException; +use PHPUnit\Framework\AssertionFailedError; use Psr\Http\Message\ResponseInterface; use Throwable; use TypeError; @@ -63,6 +64,10 @@ public function testStatusCodeInvalidArgument($statusCode) try { $this->response->withStatus($statusCode); + $this->fail('withStatus() should have raised exception on invalid argument'); + } catch (AssertionFailedError $e) { + // invalid argument not caught + throw $e; } catch (InvalidArgumentException|TypeError $e) { // valid $this->assertTrue($e instanceof Throwable); diff --git a/src/UriIntegrationTest.php b/src/UriIntegrationTest.php index 205d1f9..e77e89a 100644 --- a/src/UriIntegrationTest.php +++ b/src/UriIntegrationTest.php @@ -3,6 +3,7 @@ namespace Http\Psr7Test; use InvalidArgumentException; +use PHPUnit\Framework\AssertionFailedError; use Psr\Http\Message\UriInterface; use Throwable; use TypeError; @@ -52,6 +53,10 @@ public function testWithSchemeInvalidArguments($schema) try { $this->createUri('/')->withScheme($schema); + $this->fail('withScheme() should have raised exception on invalid argument'); + } catch (AssertionFailedError $e) { + // invalid argument not caught + throw $e; } catch (InvalidArgumentException|TypeError $e) { // valid $this->assertTrue($e instanceof Throwable); From 9bad2296dd138a074c21282168cb247e29ae259d Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 5 Apr 2023 15:06:06 -0500 Subject: [PATCH 6/8] qa: remove data provider test cases that fail without strict mode Per a comment from @simPod, removes the following: - From `RequestIntegrationTest::getInvalidMethod()`: - The test cases for 1 and 1.01 (integer and float) - From `ResponseIntegrationTest::getInvalidStatusCodeArguments()`: - The test cases for 200.34 Additionally, this patch adds keys to each entry returned by these two providers, to better facilitate understanding which test failed. The removals were necessary as the test case does not enable strict mode, and these particular types can be converted to the specified type "safely", leading to false negative results. --- src/RequestIntegrationTest.php | 10 ++++------ src/ResponseIntegrationTest.php | 11 +++++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/RequestIntegrationTest.php b/src/RequestIntegrationTest.php index f466bb4..c0a9a3a 100644 --- a/src/RequestIntegrationTest.php +++ b/src/RequestIntegrationTest.php @@ -121,12 +121,10 @@ public function testMethodWithInvalidArguments($method) public function getInvalidMethods() { return [ - [null], - [1], - [1.01], - [false], - [['foo']], - [new \stdClass()], + 'null' => [null], + 'false' => [false], + 'array' => [['foo']], + 'object' => [new \stdClass()], ]; } diff --git a/src/ResponseIntegrationTest.php b/src/ResponseIntegrationTest.php index d2ee924..41e1be5 100644 --- a/src/ResponseIntegrationTest.php +++ b/src/ResponseIntegrationTest.php @@ -83,12 +83,11 @@ public function testStatusCodeInvalidArgument($statusCode) public function getInvalidStatusCodeArguments() { return [ - [true], - ['foobar'], - [99], - [600], - [200.34], - [new \stdClass()], + 'true' => [true], + 'string' => ['foobar'], + 'too-low' => [99], + 'too-high' => [600], + 'object' => [new \stdClass()], ]; } From 138b301b9869fa8f41bb1f7a218c230dfb4d1642 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 5 Apr 2023 15:10:37 -0500 Subject: [PATCH 7/8] qa: adapt code to follow project styles Evidently, aligning operators is not allowed in this project. (I wish the required style guide was published with the project...) --- src/RequestIntegrationTest.php | 6 +++--- src/ResponseIntegrationTest.php | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/RequestIntegrationTest.php b/src/RequestIntegrationTest.php index c0a9a3a..1b21290 100644 --- a/src/RequestIntegrationTest.php +++ b/src/RequestIntegrationTest.php @@ -121,9 +121,9 @@ public function testMethodWithInvalidArguments($method) public function getInvalidMethods() { return [ - 'null' => [null], - 'false' => [false], - 'array' => [['foo']], + 'null' => [null], + 'false' => [false], + 'array' => [['foo']], 'object' => [new \stdClass()], ]; } diff --git a/src/ResponseIntegrationTest.php b/src/ResponseIntegrationTest.php index 41e1be5..7ab8534 100644 --- a/src/ResponseIntegrationTest.php +++ b/src/ResponseIntegrationTest.php @@ -83,11 +83,11 @@ public function testStatusCodeInvalidArgument($statusCode) public function getInvalidStatusCodeArguments() { return [ - 'true' => [true], - 'string' => ['foobar'], - 'too-low' => [99], + 'true' => [true], + 'string' => ['foobar'], + 'too-low' => [99], 'too-high' => [600], - 'object' => [new \stdClass()], + 'object' => [new \stdClass()], ]; } From 6608c6acc05c191c1464342b7c39529bda6a06b4 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 19 Apr 2023 13:43:21 -0500 Subject: [PATCH 8/8] qa: do not update before require Per @dbu --- .github/workflows/integration.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 9fdbf49..605523c 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -33,7 +33,6 @@ jobs: # and finally require the implementation to test with source flag (to get integration test cases that might be excluded in git-attributes) run: | composer remove --dev guzzlehttp/psr7 laminas/laminas-diactoros nyholm/psr7 ringcentral/psr7 slim/psr7 --no-update - composer update --no-interaction --no-progress composer require ${{ inputs.package }} --no-interaction --no-progress --prefer-source - name: Execute tests