From 654e3f34f2a084c487e47faa45812cdda6a5ec79 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Thu, 26 Oct 2023 05:37:44 -0500 Subject: [PATCH] feat: catch and report exception during Open-Api file validation (#45) --- composer.json | 3 +- composer.lock | 212 +++++++++++++++++++++++++++++++- src/Services/SwaggerService.php | 18 +-- tests/AutoDocControllerTest.php | 32 +++-- 4 files changed, 244 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index 8b2da35..308a6ec 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,8 @@ }, "require-dev": { "orchestra/testbench": "^6.25", - "php-coveralls/php-coveralls": "^2.5" + "php-coveralls/php-coveralls": "^2.5", + "php-mock/php-mock-phpunit": "^2.7" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 94404c6..a147170 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "57153e7c9e210ef5878d855366d22b90", + "content-hash": "d75af0ebaceddb0f9b80a70b5b9f4292", "packages": [ { "name": "brick/math", @@ -6638,6 +6638,213 @@ }, "time": "2022-09-12T20:47:09+00:00" }, + { + "name": "php-mock/php-mock", + "version": "2.4.1", + "source": { + "type": "git", + "url": "https://github.com/php-mock/php-mock.git", + "reference": "6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-mock/php-mock/zipball/6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d", + "reference": "6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0 || ^8.0", + "phpunit/php-text-template": "^1 || ^2 || ^3" + }, + "replace": { + "malkusch/php-mock": "*" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.0 || ^9.0 || ^10.0", + "squizlabs/php_codesniffer": "^3.5" + }, + "suggest": { + "php-mock/php-mock-phpunit": "Allows integration into PHPUnit testcase with the trait PHPMock." + }, + "type": "library", + "autoload": { + "files": [ + "autoload.php" + ], + "psr-4": { + "phpmock\\": [ + "classes/", + "tests/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "WTFPL" + ], + "authors": [ + { + "name": "Markus Malkusch", + "email": "markus@malkusch.de", + "homepage": "http://markus.malkusch.de", + "role": "Developer" + } + ], + "description": "PHP-Mock can mock built-in PHP functions (e.g. time()). PHP-Mock relies on PHP's namespace fallback policy. No further extension is needed.", + "homepage": "https://github.com/php-mock/php-mock", + "keywords": [ + "BDD", + "TDD", + "function", + "mock", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "issues": "https://github.com/php-mock/php-mock/issues", + "source": "https://github.com/php-mock/php-mock/tree/2.4.1" + }, + "funding": [ + { + "url": "https://github.com/michalbundyra", + "type": "github" + } + ], + "time": "2023-06-12T20:48:52+00:00" + }, + { + "name": "php-mock/php-mock-integration", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/php-mock/php-mock-integration.git", + "reference": "04f4a8d5442ca457b102b5204673f77323e3edb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/04f4a8d5442ca457b102b5204673f77323e3edb5", + "reference": "04f4a8d5442ca457b102b5204673f77323e3edb5", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "php-mock/php-mock": "^2.4", + "phpunit/php-text-template": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.27 || ^6 || ^7 || ^8 || ^9 || ^10" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpmock\\integration\\": "classes/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "WTFPL" + ], + "authors": [ + { + "name": "Markus Malkusch", + "email": "markus@malkusch.de", + "homepage": "http://markus.malkusch.de", + "role": "Developer" + } + ], + "description": "Integration package for PHP-Mock", + "homepage": "https://github.com/php-mock/php-mock-integration", + "keywords": [ + "BDD", + "TDD", + "function", + "mock", + "stub", + "test", + "test double" + ], + "support": { + "issues": "https://github.com/php-mock/php-mock-integration/issues", + "source": "https://github.com/php-mock/php-mock-integration/tree/2.2.1" + }, + "funding": [ + { + "url": "https://github.com/michalbundyra", + "type": "github" + } + ], + "time": "2023-02-13T09:51:29+00:00" + }, + { + "name": "php-mock/php-mock-phpunit", + "version": "2.7.2", + "source": { + "type": "git", + "url": "https://github.com/php-mock/php-mock-phpunit.git", + "reference": "33a99c190d078e77864b8d74cdc91cc4e5342598" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/33a99c190d078e77864b8d74cdc91cc4e5342598", + "reference": "33a99c190d078e77864b8d74cdc91cc4e5342598", + "shasum": "" + }, + "require": { + "php": ">=7", + "php-mock/php-mock-integration": "^2.2.1", + "phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10.0.17" + }, + "require-dev": { + "mockery/mockery": "^1.3.6" + }, + "type": "library", + "autoload": { + "files": [ + "autoload.php" + ], + "psr-4": { + "phpmock\\phpunit\\": "classes/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "WTFPL" + ], + "authors": [ + { + "name": "Markus Malkusch", + "email": "markus@malkusch.de", + "homepage": "http://markus.malkusch.de", + "role": "Developer" + } + ], + "description": "Mock built-in PHP functions (e.g. time()) with PHPUnit. This package relies on PHP's namespace fallback policy. No further extension is needed.", + "homepage": "https://github.com/php-mock/php-mock-phpunit", + "keywords": [ + "BDD", + "TDD", + "function", + "mock", + "phpunit", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "issues": "https://github.com/php-mock/php-mock-phpunit/issues", + "source": "https://github.com/php-mock/php-mock-phpunit/tree/2.7.2" + }, + "funding": [ + { + "url": "https://github.com/michalbundyra", + "type": "github" + } + ], + "time": "2023-06-13T07:46:04+00:00" + }, { "name": "pimple/pimple", "version": "v3.5.0", @@ -7661,7 +7868,8 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.3.0" + "php": ">=7.3.0", + "ext-json": "*" }, "platform-dev": [], "plugin-api-version": "2.3.0" diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index 105f8e6..e6e4dc1 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -697,19 +697,19 @@ public function getDocFileContent() foreach ($additionalDocs as $filePath) { $fullFilePath = base_path($filePath); - if (!file_exists($fullFilePath)) { - throw new DocFileNotExistsException($fullFilePath); - } + try { + if (!file_exists($fullFilePath)) { + throw new DocFileNotExistsException($fullFilePath); + } - $fileContent = json_decode(file_get_contents($fullFilePath), true); + $fileContent = json_decode(file_get_contents($fullFilePath), true); - if (empty($fileContent)) { - throw new EmptyDocFileException($fullFilePath); - } + if (empty($fileContent)) { + throw new EmptyDocFileException($fullFilePath); + } - try { $this->validateSpec($fileContent); - } catch (InvalidSwaggerSpecException $exception) { + } catch (DocFileNotExistsException|EmptyDocFileException|InvalidSwaggerSpecException $exception) { report($exception); continue; diff --git a/tests/AutoDocControllerTest.php b/tests/AutoDocControllerTest.php index ef2c18f..ea1f713 100644 --- a/tests/AutoDocControllerTest.php +++ b/tests/AutoDocControllerTest.php @@ -3,11 +3,13 @@ namespace RonasIT\Support\Tests; use Illuminate\Http\Response; -use RonasIT\Support\AutoDoc\Exceptions\DocFileNotExistsException; -use RonasIT\Support\AutoDoc\Exceptions\EmptyDocFileException; +use phpmock\phpunit\PHPMock; +use RonasIT\Support\Tests\Support\Traits\MockTrait; class AutoDocControllerTest extends TestCase { + use MockTrait, PHPMock; + protected $documentation; protected $localDriverFilePath; @@ -52,32 +54,44 @@ public function testGetJSONDocumentationWithAdditionalPaths() $this->assertEqualsJsonFixture('tmp_data_with_additional_paths', $response->json()); } - public function getJSONDocumentationDoesntExist() + public function testGetJSONDocumentationDoesntExist() { + $mock = $this->getFunctionMock('RonasIT\Support\AutoDoc\Services', 'report'); + $mock->expects($this->once()); + config([ 'auto-doc.additional_paths' => ['invalid_path/non_existent_file.json'] ]); - $this->expectException(DocFileNotExistsException::class); + $response = $this->json('get', '/auto-doc/documentation'); + + $response->assertStatus(Response::HTTP_OK); - $this->json('get', '/auto-doc/documentation'); + $response->assertJson($this->documentation); } - public function getJSONDocumentationIsEmpty() + public function testGetJSONDocumentationIsEmpty() { + $mock = $this->getFunctionMock('RonasIT\Support\AutoDoc\Services', 'report'); + $mock->expects($this->once()); + config([ 'auto-doc.additional_paths' => ['tests/fixtures/AutoDocControllerTest/documentation__non_json.txt'] ]); - $this->expectException(EmptyDocFileException::class); + $response = $this->json('get', '/auto-doc/documentation'); - $this->json('get', '/auto-doc/documentation'); + $response->assertStatus(Response::HTTP_OK); + + $response->assertJson($this->documentation); } public function testGetJSONDocumentationInvalidAdditionalDoc() { config([ - 'auto-doc.additional_paths' => ['tests/fixtures/AutoDocControllerTest/documentation__invalid_format__missing_field__paths.json'] + 'auto-doc.additional_paths' => [ + 'tests/fixtures/AutoDocControllerTest/documentation__invalid_format__missing_field__paths.json' + ] ]); $response = $this->json('get', '/auto-doc/documentation');