diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index c362142..f970da5 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -67,7 +67,7 @@ jobs: run: "vendor/bin/phpunit --coverage-clover=coverage.xml" - name: "Upload coverage file" - uses: "actions/upload-artifact@v2" + uses: "actions/upload-artifact@v4" with: name: "phpunit-${{ matrix.php-version }}-${{ matrix.dependencies }}-${{ matrix.dbal-version }}.coverage" path: "coverage.xml" diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 39335a6..b188595 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -12,14 +12,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Validate composer.json and composer.lock run: composer validate --strict - name: Cache Composer packages id: composer-cache - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: vendor key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml deleted file mode 100644 index 4a3f43c..0000000 --- a/.github/workflows/static-analysis.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: "Static analysis" - -on: - pull_request: - branches: - - "*.x" - - "main" - push: - branches: - - "*.x" - - "main" - -jobs: - psalm: - name: "Static Analysis" - runs-on: ubuntu-latest - - steps: - - uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e - with: - php-version: '8.1' - - uses: actions/checkout@v2 - - name: Install Dependencies - run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist - - name: Execute tests (Unit and Feature tests) via PHPUnit - run: vendor/bin/psalm diff --git a/.gitignore b/.gitignore index 89d0f12..d4950c8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ composer.lock /.phpcs-cache /coverage/ /.phpunit.cache/ +.phpunit.result.cache diff --git a/composer.json b/composer.json index aaf7fc2..c8cb178 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,17 @@ "source": "https://github.com/api-skeletons/laravel-api-problem", "chat": "https://gitter.im/API-Skeletons/open-source" }, + "require": { + "php": "^8.1", + "doctrine/instantiator": "^2.0", + "laravel/framework": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0", + "orchestra/testbench": "^v10.1", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpunit/phpunit": "^11.5" + }, "config": { "sort-packages": true, "allow-plugins": { @@ -48,20 +59,7 @@ "test": [ "vendor/bin/parallel-lint src test", "vendor/bin/phpcs", - "vendor/bin/psalm", "vendor/bin/phpunit" ] - }, - "require": { - "php": "^8.1", - "doctrine/instantiator": "^2.0", - "laravel/framework": "^8.0 || ^9.0 || ^10.0 || ^11.0" - }, - "require-dev": { - "doctrine/coding-standard": "^12.0", - "orchestra/testbench": "^7.41", - "php-parallel-lint/php-parallel-lint": "^1.4", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4.15" } } diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index 7c0333d..0000000 --- a/psalm.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/test/ApiProblemTest.php b/test/ApiProblemTest.php index 476c2a1..71190f6 100644 --- a/test/ApiProblemTest.php +++ b/test/ApiProblemTest.php @@ -7,7 +7,6 @@ use ApiSkeletons\Laravel\ApiProblem\ApiProblem; use ApiSkeletons\Laravel\ApiProblem\Exception; use ApiSkeletons\Laravel\ApiProblem\Facades\ApiProblem as ApiProblemFacade; -use http\Exception\InvalidArgumentException; use Illuminate\Http\JsonResponse; use ReflectionObject; use TypeError; @@ -15,7 +14,7 @@ final class ApiProblemTest extends TestCase { /** @psalm-return array */ - public function statusCodes(): array + public static function statusCodes(): array { return [ '200' => [200], @@ -42,25 +41,21 @@ public function testResponseWithFacade(): void $this->assertInstanceOf(JsonResponse::class, ApiProblemFacade::response('Testing', 500)); } - /** - * @dataProvider statusCodes - */ + /** @dataProvider statusCodes */ public function testStatusIsUsedVerbatim(int $status): void { $apiProblem = new ApiProblem($status, 'foo'); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('status', $payload); $this->assertEquals($status, $payload['status']); } - /** - * @requires PHP 7.0 - */ + /** @requires PHP 7.0 */ public function testErrorAsDetails(): void { - $error = new TypeError('error message', 705); + $error = new TypeError('error message', 705); $apiProblem = new ApiProblem(500, $error); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('title', $payload); $this->assertEquals('TypeError', $payload['title']); @@ -72,9 +67,9 @@ public function testErrorAsDetails(): void public function testExceptionCodeIsUsedForStatus(): void { - $exception = new \Exception('exception message', 401); + $exception = new \Exception('exception message', 401); $apiProblem = new ApiProblem('500', $exception); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('status', $payload); $this->assertEquals($exception->getCode(), $payload['status']); } @@ -82,23 +77,23 @@ public function testExceptionCodeIsUsedForStatus(): void public function testDetailStringIsUsedVerbatim(): void { $apiProblem = new ApiProblem('500', 'foo'); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('detail', $payload); $this->assertEquals('foo', $payload['detail']); } public function testExceptionMessageIsUsedForDetail(): void { - $exception = new \Exception('exception message'); + $exception = new \Exception('exception message'); $apiProblem = new ApiProblem('500', $exception); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('detail', $payload); $this->assertEquals($exception->getMessage(), $payload['detail']); } public function testExceptionsCanTriggerInclusionOfStackTraceInDetails(): void { - $exception = new \Exception('exception message'); + $exception = new \Exception('exception message'); $apiProblem = new ApiProblem('500', $exception); $apiProblem->setDetailIncludesStackTrace(true); $payload = $apiProblem->toArray(); @@ -109,7 +104,7 @@ public function testExceptionsCanTriggerInclusionOfStackTraceInDetails(): void public function testExceptionsCanTriggerInclusionOfNestedExceptions(): void { - $exceptionChild = new \Exception('child exception'); + $exceptionChild = new \Exception('child exception'); $exceptionParent = new \Exception('parent exception', 0, $exceptionChild); $apiProblem = new ApiProblem('500', $exceptionParent); @@ -130,13 +125,13 @@ public function testExceptionsCanTriggerInclusionOfNestedExceptions(): void public function testTypeUrlIsUsedVerbatim(): void { $apiProblem = new ApiProblem('500', 'foo', 'http://status.dev:8080/details.md'); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('type', $payload); $this->assertEquals('http://status.dev:8080/details.md', $payload['type']); } /** @psalm-return array */ - public function knownStatusCodes(): array + public static function knownStatusCodes(): array { return [ '404' => [404], @@ -146,14 +141,12 @@ public function knownStatusCodes(): array ]; } - /** - * @dataProvider knownStatusCodes - */ + /** @dataProvider knownStatusCodes */ public function testKnownStatusResultsInKnownTitle(int $status): void { $apiProblem = new ApiProblem($status, 'foo'); - $r = new ReflectionObject($apiProblem); - $p = $r->getProperty('problemStatusTitles'); + $r = new ReflectionObject($apiProblem); + $p = $r->getProperty('problemStatusTitles'); $p->setAccessible(true); $titles = $p->getValue($apiProblem); @@ -165,7 +158,7 @@ public function testKnownStatusResultsInKnownTitle(int $status): void public function testUnknownStatusResultsInUnknownTitle(): void { $apiProblem = new ApiProblem(420, 'foo'); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('title', $payload); $this->assertEquals('Unknown', $payload['title']); } @@ -173,7 +166,7 @@ public function testUnknownStatusResultsInUnknownTitle(): void public function testProvidedTitleIsUsedVerbatim(): void { $apiProblem = new ApiProblem('500', 'foo', 'http://status.dev:8080/details.md', 'some title'); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('title', $payload); $this->assertEquals('some title', $payload['title']); } @@ -185,7 +178,7 @@ public function testCanPassArbitraryDetailsToConstructor(): void 'Invalid input', 'http://example.com/api/problem/400', 'Invalid entity', - ['foo' => 'bar'] + ['foo' => 'bar'], ); $this->assertEquals('bar', $problem->foo); } @@ -197,9 +190,9 @@ public function testArraySerializationIncludesArbitraryDetails(): void 'Invalid input', 'http://example.com/api/problem/400', 'Invalid entity', - ['foo' => 'bar'] + ['foo' => 'bar'], ); - $array = $problem->toArray(); + $array = $problem->toArray(); $this->assertArrayHasKey('foo', $array); $this->assertEquals('bar', $array['foo']); } @@ -211,9 +204,9 @@ public function testArbitraryDetailsShouldNotOverwriteRequiredFieldsInArraySeria 'Invalid input', 'http://example.com/api/problem/400', 'Invalid entity', - ['title' => 'SHOULD NOT GET THIS'] + ['title' => 'SHOULD NOT GET THIS'], ); - $array = $problem->toArray(); + $array = $problem->toArray(); $this->assertArrayHasKey('title', $array); $this->assertEquals('Invalid entity', $array['title']); } @@ -223,7 +216,7 @@ public function testUsesTitleFromExceptionWhenProvided(): void $exception = new Exception\DomainException('exception message', 401); $exception->setTitle('problem title'); $apiProblem = new ApiProblem('401', $exception); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('title', $payload); $this->assertEquals($exception->getTitle(), $payload['title']); } @@ -233,7 +226,7 @@ public function testUsesTypeFromExceptionWhenProvided(): void $exception = new Exception\DomainException('exception message', 401); $exception->setType('http://example.com/api/help/401'); $apiProblem = new ApiProblem('401', $exception); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('type', $payload); $this->assertEquals($exception->getType(), $payload['type']); } @@ -243,13 +236,13 @@ public function testUsesAdditionalDetailsFromExceptionWhenProvided(): void $exception = new Exception\DomainException('exception message', 401); $exception->setAdditionalDetails(['foo' => 'bar']); $apiProblem = new ApiProblem('401', $exception); - $payload = $apiProblem->toArray(); + $payload = $apiProblem->toArray(); $this->assertArrayHasKey('foo', $payload); $this->assertEquals('bar', $payload['foo']); } /** @psalm-return array */ - public function invalidStatusCodes(): array + public static function invalidStatusCodes(): array { return [ '-1' => [-1], @@ -266,7 +259,7 @@ public function invalidStatusCodes(): array */ public function testInvalidHttpStatusCodesAreCastTo500(int $code): void { - $e = new \Exception('Testing', $code); + $e = new \Exception('Testing', $code); $problem = new ApiProblem($code, $e); $this->assertEquals(500, $problem->status); }