From 5af85dc757ec54aae2d0b345be597f494fbd4b14 Mon Sep 17 00:00:00 2001 From: nktkvlv Date: Tue, 8 Apr 2025 12:40:43 +0600 Subject: [PATCH 01/19] feat: move error message to description --- config/auto-doc.php | 11 ++++- resources/views/swagger-error.blade.php | 1 + src/AutoDocServiceProvider.php | 4 ++ src/Drivers/LocalDriver.php | 2 +- src/Drivers/RemoteDriver.php | 2 +- src/Drivers/StorageDriver.php | 2 +- src/Services/SwaggerService.php | 43 ++++++++++------ tests/SwaggerServiceTest.php | 65 +++---------------------- 8 files changed, 55 insertions(+), 75 deletions(-) create mode 100644 resources/views/swagger-error.blade.php diff --git a/config/auto-doc.php b/config/auto-doc.php index 7f432209..a47d261a 100644 --- a/config/auto-doc.php +++ b/config/auto-doc.php @@ -101,6 +101,15 @@ '204' => 'Operation successfully done', '404' => 'This entity not found', ], + + /* + |-------------------------------------------------------------------------- + | Error Template + |-------------------------------------------------------------------------- + | + | You can use your custom description view for errors. + */ + 'error' => 'auto-doc::swagger-error', ], /* @@ -184,5 +193,5 @@ 'development', ], - 'config_version' => '2.8', + 'config_version' => '2.9', ]; diff --git a/resources/views/swagger-error.blade.php b/resources/views/swagger-error.blade.php new file mode 100644 index 00000000..0b9291cb --- /dev/null +++ b/resources/views/swagger-error.blade.php @@ -0,0 +1 @@ +{{ $message }} \ No newline at end of file diff --git a/src/AutoDocServiceProvider.php b/src/AutoDocServiceProvider.php index 0e6d435b..5158654d 100644 --- a/src/AutoDocServiceProvider.php +++ b/src/AutoDocServiceProvider.php @@ -19,6 +19,10 @@ public function boot() __DIR__ . '/../resources/views/swagger-description.blade.php' => resource_path('views/vendor/auto-doc/swagger-description.blade.php'), ], 'view'); + $this->publishes([ + __DIR__ . '/../resources/views/swagger-error.blade.php' => resource_path('views/vendor/auto-doc/swagger-error.blade.php'), + ], 'view'); + if (!$this->app->routesAreCached()) { require __DIR__ . '/Http/routes.php'; } diff --git a/src/Drivers/LocalDriver.php b/src/Drivers/LocalDriver.php index f8b7f279..117389cf 100755 --- a/src/Drivers/LocalDriver.php +++ b/src/Drivers/LocalDriver.php @@ -30,7 +30,7 @@ public function saveData(): void public function getDocumentation(): array { if (!file_exists($this->prodFilePath)) { - throw new FileNotFoundException(); + throw new FileNotFoundException("Documentation file not found :{$this->prodFilePath}"); } $fileContent = file_get_contents($this->prodFilePath); diff --git a/src/Drivers/RemoteDriver.php b/src/Drivers/RemoteDriver.php index 16b52334..ade049c4 100755 --- a/src/Drivers/RemoteDriver.php +++ b/src/Drivers/RemoteDriver.php @@ -36,7 +36,7 @@ public function getDocumentation(): array list($content, $statusCode) = $this->makeHttpRequest('get', $this->getUrl()); if (empty($content) || $statusCode !== 200) { - throw new FileNotFoundException(); + throw new FileNotFoundException('Documentation file not found.'); } return json_decode($content, true); diff --git a/src/Drivers/StorageDriver.php b/src/Drivers/StorageDriver.php index e08646dd..972dea0e 100755 --- a/src/Drivers/StorageDriver.php +++ b/src/Drivers/StorageDriver.php @@ -34,7 +34,7 @@ public function saveData(): void public function getDocumentation(): array { if (!$this->disk->exists($this->prodFilePath)) { - throw new FileNotFoundException(); + throw new FileNotFoundException("Documentation file not found :{$this->prodFilePath}"); } $fileContent = $this->disk->get($this->prodFilePath); diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index b70ad14b..06be0fdf 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -138,7 +138,21 @@ protected function generateEmptyData(): array throw new EmptyContactEmailException(); } - $data = [ + $data = $this->generateBaseDataObject(); + $data['info'] = $this->prepareInfo($this->config['info']); + + $securityDefinitions = $this->generateSecurityDefinition(); + + if (!empty($securityDefinitions)) { + $data['securityDefinitions'] = $securityDefinitions; + } + + return $data; + } + + protected function generateBaseDataObject(): array + { + return [ 'openapi' => self::OPEN_API_VERSION, 'servers' => [ ['url' => URL::query($this->config['basePath'])], @@ -147,16 +161,7 @@ protected function generateEmptyData(): array 'components' => [ 'schemas' => $this->config['definitions'], ], - 'info' => $this->prepareInfo($this->config['info']) ]; - - $securityDefinitions = $this->generateSecurityDefinition(); - - if (!empty($securityDefinitions)) { - $data['securityDefinitions'] = $securityDefinitions; - } - - return $data; } protected function generateSecurityDefinition(): ?array @@ -804,9 +809,19 @@ public function saveProductionData() public function getDocFileContent() { - $documentation = $this->driver->getDocumentation(); + try { + $documentation = $this->driver->getDocumentation(); + + $this->openAPIValidator->validate($documentation); + } catch (\Exception $exception) { + $data = $this->generateBaseDataObject(); - $this->openAPIValidator->validate($documentation); + $this->config['info'] = Arr::set($this->config, 'info.description', Arr::get($this->config, 'defaults.error')); + + $data['info'] = $this->prepareInfo($this->config['info'], ['message' => $exception->getMessage()]); + + return $data; + } $additionalDocs = config('auto-doc.additional_paths', []); @@ -931,7 +946,7 @@ protected function getDefaultValueByType($type) return $values[$type]; } - protected function prepareInfo(array $info): array + protected function prepareInfo(array $info, array $descriptionData = []): array { if (empty($info)) { return $info; @@ -948,7 +963,7 @@ protected function prepareInfo(array $info): array } if (!empty($info['description'])) { - $info['description'] = view($info['description'])->render(); + $info['description'] = view($info['description'], $descriptionData)->render(); } return $info; diff --git a/tests/SwaggerServiceTest.php b/tests/SwaggerServiceTest.php index 3ae474ab..5aae1ad9 100644 --- a/tests/SwaggerServiceTest.php +++ b/tests/SwaggerServiceTest.php @@ -3,24 +3,12 @@ namespace RonasIT\AutoDoc\Tests; use Illuminate\Http\Testing\File; +use Illuminate\Support\Arr; +use Illuminate\Support\Str; use PHPUnit\Framework\Attributes\DataProvider; use RonasIT\AutoDoc\Exceptions\EmptyContactEmailException; use RonasIT\AutoDoc\Exceptions\InvalidDriverClassException; use RonasIT\AutoDoc\Exceptions\LegacyConfigException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\DuplicateFieldException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\DuplicateParamException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\DuplicatePathPlaceholderException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidFieldValueException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidPathException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidStatusCodeException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidSwaggerSpecException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidSwaggerVersionException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingExternalRefException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingLocalRefException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingFieldException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingPathParamException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingPathPlaceholderException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingRefFileException; use RonasIT\AutoDoc\Exceptions\SwaggerDriverClassNotFoundException; use RonasIT\AutoDoc\Exceptions\UnsupportedDocumentationViewerException; use RonasIT\AutoDoc\Exceptions\WrongSecurityConfigException; @@ -90,215 +78,178 @@ public static function getConstructorInvalidTmpData(): array return [ [ 'tmpDoc' => 'documentation/invalid_version', - 'exception' => InvalidSwaggerVersionException::class, - 'exceptionMessage' => "Unrecognized Swagger version '1.0'. Expected 3.1.0.", + 'exceptionMessage' => "Validation failed. Unrecognized Swagger version '1.0'. Expected 3.1.0.", ], [ 'tmpDoc' => 'documentation/invalid_format__array_parameter__no_items', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. paths./users.post.parameters.0 is an " . "array, so it must include an 'items' field.", ], [ 'tmpDoc' => 'documentation/invalid_format__array_response_body__no_items', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. paths./users.get.responses.200.schema is an array, " . "so it must include an 'items' field.", ], [ 'tmpDoc' => 'documentation/invalid_format__array_response_header__no_items', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. paths./users.get.responses.default.headers." . "Last-Modified is an array, so it must include an 'items' field.", ], [ 'tmpDoc' => 'documentation/invalid_format__body_and_form_params', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.post' " . "has body and formData parameters. Only one or the other is allowed.", ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_header_params', - 'exception' => DuplicateParamException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.get' " . "has multiple in:header parameters with name:foo.", ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_path_params', - 'exception' => DuplicateParamException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.get' has " - . "multiple in:path parameters with name:username", + . "multiple in:path parameters with name:username.", ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_path_placeholders', - 'exception' => DuplicatePathPlaceholderException::class, 'exceptionMessage' => "Validation failed. Path '/users/{username}/profile/{username}/image/{img_id}' " . "has multiple path placeholders with name: username.", ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_operation_id', - 'exception' => DuplicateFieldException::class, 'exceptionMessage' => "Validation failed. Found multiple fields 'paths.*.*.operationId' " . "with values: addPet.", ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_tag', - 'exception' => DuplicateFieldException::class, 'exceptionMessage' => "Validation failed. Found multiple fields 'tags.*.name' with values: user.", ], [ 'tmpDoc' => 'documentation/invalid_format__file_invalid_consumes', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}/profile/image.post' " . "has body and formData parameters. Only one or the other is allowed.", ], [ 'tmpDoc' => 'documentation/invalid_format__file_no_consumes', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}/profile/image.post' " . "has body and formData parameters. Only one or the other is allowed.", ], [ 'tmpDoc' => 'documentation/invalid_format__multiple_body_params', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.get' has 2 body " . "parameters. Only one is allowed.", ], [ 'tmpDoc' => 'documentation/invalid_format__no_path_params', - 'exception' => MissingPathParamException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}/{foo}.get' has " . "no params for placeholders: username, foo.", ], [ 'tmpDoc' => 'documentation/invalid_format__path_param_no_placeholder', - 'exception' => MissingPathPlaceholderException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.post' has no " . "placeholders for params: foo.", ], [ 'tmpDoc' => 'documentation/invalid_format__invalid_value__path', - 'exception' => InvalidPathException::class, 'exceptionMessage' => "Validation failed. Incorrect 'paths.users'. Paths should only have path " . "names that starts with `/`.", ], [ 'tmpDoc' => 'documentation/invalid_format__invalid_value__status_code', - 'exception' => InvalidStatusCodeException::class, 'exceptionMessage' => "Validation failed. Operation at 'paths./users.get.responses.8888' should " . "only have three-digit status codes, `default`, and vendor extensions (`x-*`) as properties.", ], [ 'tmpDoc' => 'documentation/invalid_format__invalid_value__parameter_in', - 'exception' => InvalidFieldValueException::class, 'exceptionMessage' => "Validation failed. Field 'paths./auth/login.post.parameters.0.in' " . "has an invalid value: invalid_in. Allowed values: body, formData, query, path, header.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__paths', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. '' should have required fields: paths.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__operation_responses', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. 'paths./auth/login.post' should have required " . "fields: responses.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__parameter_in', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. 'paths./auth/login.post.parameters.0' should " . "have required fields: in.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__response_description', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. 'paths./auth/login.post.responses.200' should " . "have required fields: description.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__definition_type', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. 'components.schemas.authloginObject' should have " . "required fields: type.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__info_version', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. 'info' should have required fields: version.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__items_type', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. 'paths./pet/findByStatus.get.parameters.0.schema.items' " . "should have required fields: type.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__header_type', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. 'paths./user/login.get.responses.200.headers.X-Rate-Limit' " . "should have required fields: type.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__tag_name', - 'exception' => MissingFieldException::class, 'exceptionMessage' => "Validation failed. 'tags.0' should have required fields: name.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_local_ref', - 'exception' => MissingLocalRefException::class, 'exceptionMessage' => "Validation failed. Ref 'loginObject' is used in \$ref but not defined " . "in 'definitions' field.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_external_ref', - 'exception' => MissingExternalRefException::class, 'exceptionMessage' => "Validation failed. Ref 'authloginObject' is used in \$ref but not defined " . "in 'tests/fixtures/SwaggerServiceTest/documentation/with_definitions.json' file.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_ref_file', - 'exception' => MissingRefFileException::class, 'exceptionMessage' => "Validation failed. Filename 'invalid-filename.json' is used in \$ref but " . "file doesn't exist.", ], [ 'tmpDoc' => 'documentation/invalid_format__invalid_schema_type', - 'exception' => InvalidFieldValueException::class, 'exceptionMessage' => "Validation failed. Field 'paths./users.get.responses.200.schema.type' " . "has an invalid value: something. Allowed values: array, boolean, integer, number, " . "string, object, null, undefined, file.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_path_parameter', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Path parameters cannot be optional. " . "Set required=true for the 'username' parameters at operation 'paths./users.get'.", ], [ 'tmpDoc' => 'documentation/invalid_format__security_definition__type', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Field 'securityDefinitions.0.type' has an invalid value: invalid. Allowed values: basic, apiKey, oauth2.", ], [ 'tmpDoc' => 'documentation/invalid_format__security_definition__flow', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Field 'securityDefinitions.0.flow' has an invalid value: invalid. Allowed values: implicit, password, application, accessCode.", ], [ 'tmpDoc' => 'documentation/invalid_format__security_definition__in', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Field 'securityDefinitions.0.in' has an invalid value: invalid. Allowed values: query, header.", ], [ 'tmpDoc' => 'documentation/invalid_format__request_body__invalid_content', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. Operation 'paths./users/{id}.post' has invalid content types: image/png.", ], [ 'tmpDoc' => 'documentation/invalid_format__response__invalid_items', - 'exception' => InvalidSwaggerSpecException::class, 'exceptionMessage' => "Validation failed. 'paths./users/{id}.post.responses.200.schema.items' should have required fields: type.", ], ]; @@ -307,15 +258,15 @@ public static function getConstructorInvalidTmpData(): array #[DataProvider('getConstructorInvalidTmpData')] public function testGetDocFileContentInvalidTmpData( string $tmpDoc, - string $exception, string $exceptionMessage, ) { $this->mockDriverGetDocumentation($this->getJsonFixture($tmpDoc)); - $this->expectException($exception); - $this->expectExceptionMessage($exceptionMessage); + $content = app(SwaggerService::class)->getDocFileContent(); - app(SwaggerService::class)->getDocFileContent(); + $description = Arr::get($content, 'info.description'); + + $this->assertEquals($exceptionMessage, Str::replace(''', "'", $description)); } public function testEmptyContactEmail() From 1a5833d282c460abefab63674686ccdbf1ac5f47 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Sun, 11 May 2025 15:22:20 +0300 Subject: [PATCH 02/19] fix:tests --- config/auto-doc.php | 2 +- tests/SwaggerServiceTest.php | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/config/auto-doc.php b/config/auto-doc.php index a4fea346..d010d70a 100644 --- a/config/auto-doc.php +++ b/config/auto-doc.php @@ -192,7 +192,7 @@ 'local', 'development', ], - + /* |-------------------------------------------------------------------------- | Paratests diff --git a/tests/SwaggerServiceTest.php b/tests/SwaggerServiceTest.php index 5919206b..5fae50e8 100644 --- a/tests/SwaggerServiceTest.php +++ b/tests/SwaggerServiceTest.php @@ -227,13 +227,11 @@ public static function getConstructorInvalidTmpData(): array ], [ 'tmpDoc' => 'documentation/invalid_format__missing_external_ref', - 'exception' => MissingExternalRefException::class, 'exceptionMessage' => "Validation failed. Ref 'authloginObject' is used in \$ref but not defined " . "in 'tests/fixtures/SwaggerServiceTest/documentation/with_definitions.json' file.", ], [ 'tmpDoc' => 'documentation/invalid_format__missing_ref_file', - 'exception' => MissingRefFileException::class, 'exceptionMessage' => "Validation failed. Filename 'invalid-filename.json' is used in \$ref but " . "file doesn't exist.", ], From eff77988535b070e065144ad4bded74cfd123831 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Sun, 11 May 2025 17:18:37 +0300 Subject: [PATCH 03/19] refactor: remove config change in getDocFileContent method --- config/auto-doc.php | 2 +- ...wagger-error.blade.php => error.blade.php} | 0 src/AutoDocServiceProvider.php | 2 +- src/Drivers/LocalDriver.php | 2 +- src/Services/SwaggerService.php | 8 +++--- tests/SwaggerServiceTest.php | 25 +++++-------------- 6 files changed, 14 insertions(+), 25 deletions(-) rename resources/views/{swagger-error.blade.php => error.blade.php} (100%) diff --git a/config/auto-doc.php b/config/auto-doc.php index d010d70a..379a2a7e 100644 --- a/config/auto-doc.php +++ b/config/auto-doc.php @@ -109,7 +109,7 @@ | | You can use your custom description view for errors. */ - 'error' => 'auto-doc::swagger-error', + 'error' => 'auto-doc::error', ], /* diff --git a/resources/views/swagger-error.blade.php b/resources/views/error.blade.php similarity index 100% rename from resources/views/swagger-error.blade.php rename to resources/views/error.blade.php diff --git a/src/AutoDocServiceProvider.php b/src/AutoDocServiceProvider.php index 5158654d..7b92fb17 100644 --- a/src/AutoDocServiceProvider.php +++ b/src/AutoDocServiceProvider.php @@ -20,7 +20,7 @@ public function boot() ], 'view'); $this->publishes([ - __DIR__ . '/../resources/views/swagger-error.blade.php' => resource_path('views/vendor/auto-doc/swagger-error.blade.php'), + __DIR__ . '/../resources/views/error.blade.php' => resource_path('views/vendor/auto-doc/error.blade.php'), ], 'view'); if (!$this->app->routesAreCached()) { diff --git a/src/Drivers/LocalDriver.php b/src/Drivers/LocalDriver.php index e0d89c80..bd87a1bd 100755 --- a/src/Drivers/LocalDriver.php +++ b/src/Drivers/LocalDriver.php @@ -30,7 +30,7 @@ public function saveData(): void public function getDocumentation(): array { if (!file_exists($this->prodFilePath)) { - throw new FileNotFoundException("Documentation file not found :{$this->prodFilePath}"); + throw new FileNotFoundException($this->prodFilePath); } $fileContent = file_get_contents($this->prodFilePath); diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index ed77d8c0..8fa44d27 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -23,6 +23,7 @@ use RonasIT\AutoDoc\Traits\GetDependenciesTrait; use RonasIT\AutoDoc\Validators\SwaggerSpecValidator; use Symfony\Component\HttpFoundation\Response; +use Exception; /** * @property SwaggerDriverContract $driver @@ -826,12 +827,13 @@ public function getDocFileContent() $documentation = $this->driver->getDocumentation(); $this->openAPIValidator->validate($documentation); - } catch (\Exception $exception) { + } catch (Exception $exception) { $data = $this->generateBaseDataObject(); - $this->config['info'] = Arr::set($this->config, 'info.description', Arr::get($this->config, 'defaults.error')); + $infoConfig = $this->config['info']; + $infoConfig['description'] = Arr::get($this->config, 'defaults.error'); - $data['info'] = $this->prepareInfo($this->config['info'], ['message' => $exception->getMessage()]); + $data['info'] = $this->prepareInfo($infoConfig, ['message' => $exception->getMessage()]); return $data; } diff --git a/tests/SwaggerServiceTest.php b/tests/SwaggerServiceTest.php index 5fae50e8..eda71fbc 100644 --- a/tests/SwaggerServiceTest.php +++ b/tests/SwaggerServiceTest.php @@ -3,26 +3,11 @@ namespace RonasIT\AutoDoc\Tests; use Illuminate\Http\Testing\File; -use Illuminate\Support\Arr; -use Illuminate\Support\Str; +use Illuminate\Support\Facades\View; use PHPUnit\Framework\Attributes\DataProvider; use RonasIT\AutoDoc\Exceptions\EmptyContactEmailException; use RonasIT\AutoDoc\Exceptions\InvalidDriverClassException; use RonasIT\AutoDoc\Exceptions\LegacyConfigException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\DuplicateFieldException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\DuplicateParamException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\DuplicatePathPlaceholderException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidFieldValueException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidPathException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidStatusCodeException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidSwaggerSpecException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\InvalidSwaggerVersionException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingExternalRefException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingFieldException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingLocalRefException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingPathParamException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingPathPlaceholderException; -use RonasIT\AutoDoc\Exceptions\SpecValidation\MissingRefFileException; use RonasIT\AutoDoc\Exceptions\SwaggerDriverClassNotFoundException; use RonasIT\AutoDoc\Exceptions\UnsupportedDocumentationViewerException; use RonasIT\AutoDoc\Exceptions\WrongSecurityConfigException; @@ -276,11 +261,13 @@ public function testGetDocFileContentInvalidTmpData( ) { $this->mockDriverGetDocumentation($this->getJsonFixture($tmpDoc)); - $content = app(SwaggerService::class)->getDocFileContent(); + app(SwaggerService::class)->getDocFileContent($exceptionMessage); - $description = Arr::get($content, 'info.description'); + View::addLocation(__DIR__ . '/../resources/views'); - $this->assertEquals($exceptionMessage, Str::replace(''', "'", $description)); + $rendered = view('error', ['message' => $exceptionMessage])->render(); + + $this->assertStringContainsString($exceptionMessage, html_entity_decode($rendered)); } public function testEmptyContactEmail() From cb39739b9846f0cd3d81d99b117bdea3bff784e4 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Sun, 11 May 2025 17:21:25 +0300 Subject: [PATCH 04/19] refactor: revert generateEmptyData method codestyle --- src/Services/SwaggerService.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index 8fa44d27..e13a1343 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -140,8 +140,17 @@ protected function generateEmptyData(): array throw new EmptyContactEmailException(); } - $data = $this->generateBaseDataObject(); - $data['info'] = $this->prepareInfo($this->config['info']); + $data = [ + 'openapi' => self::OPEN_API_VERSION, + 'servers' => [ + ['url' => URL::query($this->config['basePath'])], + ], + 'paths' => [], + 'components' => [ + 'schemas' => $this->config['definitions'], + ], + 'info' => $this->prepareInfo($this->config['info']) + ]; $securityDefinitions = $this->generateSecurityDefinition(); From 9973e713914dc1dbca7bcff3572ddadf944d2d1e Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Sun, 11 May 2025 17:30:17 +0300 Subject: [PATCH 05/19] fix: remove useless argument --- tests/SwaggerServiceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SwaggerServiceTest.php b/tests/SwaggerServiceTest.php index eda71fbc..ce934bab 100644 --- a/tests/SwaggerServiceTest.php +++ b/tests/SwaggerServiceTest.php @@ -261,7 +261,7 @@ public function testGetDocFileContentInvalidTmpData( ) { $this->mockDriverGetDocumentation($this->getJsonFixture($tmpDoc)); - app(SwaggerService::class)->getDocFileContent($exceptionMessage); + app(SwaggerService::class)->getDocFileContent(); View::addLocation(__DIR__ . '/../resources/views'); From f3323a1f03c17b5074e97c7e3e3be648d4a5b8e7 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Tue, 13 May 2025 17:34:37 +0300 Subject: [PATCH 06/19] refactor: use arguments in generateEmptyData --- config/auto-doc.php | 2 +- src/AutoDocServiceProvider.php | 3 --- src/Drivers/LocalDriver.php | 2 +- src/Drivers/RemoteDriver.php | 2 +- src/Drivers/StorageDriver.php | 4 ++-- src/Exceptions/FileNotFoundException.php | 17 +++++++++++++++++ src/Services/SwaggerService.php | 13 ++++++------- 7 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 src/Exceptions/FileNotFoundException.php diff --git a/config/auto-doc.php b/config/auto-doc.php index 379a2a7e..4245ad74 100644 --- a/config/auto-doc.php +++ b/config/auto-doc.php @@ -220,5 +220,5 @@ ], ], - 'config_version' => '2.9', + 'config_version' => '2.10', ]; diff --git a/src/AutoDocServiceProvider.php b/src/AutoDocServiceProvider.php index 7b92fb17..fafd6bcb 100644 --- a/src/AutoDocServiceProvider.php +++ b/src/AutoDocServiceProvider.php @@ -17,9 +17,6 @@ public function boot() $this->publishes([ __DIR__ . '/../resources/views/swagger-description.blade.php' => resource_path('views/vendor/auto-doc/swagger-description.blade.php'), - ], 'view'); - - $this->publishes([ __DIR__ . '/../resources/views/error.blade.php' => resource_path('views/vendor/auto-doc/error.blade.php'), ], 'view'); diff --git a/src/Drivers/LocalDriver.php b/src/Drivers/LocalDriver.php index bd87a1bd..b5d6288e 100755 --- a/src/Drivers/LocalDriver.php +++ b/src/Drivers/LocalDriver.php @@ -2,7 +2,7 @@ namespace RonasIT\AutoDoc\Drivers; -use Illuminate\Contracts\Filesystem\FileNotFoundException; +use RonasIT\AutoDoc\Exceptions\FileNotFoundException; use RonasIT\AutoDoc\Exceptions\MissedProductionFilePathException; class LocalDriver extends BaseDriver diff --git a/src/Drivers/RemoteDriver.php b/src/Drivers/RemoteDriver.php index b85921ac..db5e6e7f 100755 --- a/src/Drivers/RemoteDriver.php +++ b/src/Drivers/RemoteDriver.php @@ -2,7 +2,7 @@ namespace RonasIT\AutoDoc\Drivers; -use Illuminate\Contracts\Filesystem\FileNotFoundException; +use RonasIT\AutoDoc\Exceptions\FileNotFoundException; use RonasIT\AutoDoc\Exceptions\MissedRemoteDocumentationUrlException; class RemoteDriver extends BaseDriver diff --git a/src/Drivers/StorageDriver.php b/src/Drivers/StorageDriver.php index 2389f651..71cd95d6 100755 --- a/src/Drivers/StorageDriver.php +++ b/src/Drivers/StorageDriver.php @@ -2,7 +2,7 @@ namespace RonasIT\AutoDoc\Drivers; -use Illuminate\Contracts\Filesystem\FileNotFoundException; +use RonasIT\AutoDoc\Exceptions\FileNotFoundException; use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Support\Facades\Storage; use RonasIT\AutoDoc\Exceptions\MissedProductionFilePathException; @@ -34,7 +34,7 @@ public function saveData(): void public function getDocumentation(): array { if (!$this->disk->exists($this->prodFilePath)) { - throw new FileNotFoundException("Documentation file not found :{$this->prodFilePath}"); + throw new FileNotFoundException($this->prodFilePath); } $fileContent = $this->disk->get($this->prodFilePath); diff --git a/src/Exceptions/FileNotFoundException.php b/src/Exceptions/FileNotFoundException.php new file mode 100644 index 00000000..88a65a08 --- /dev/null +++ b/src/Exceptions/FileNotFoundException.php @@ -0,0 +1,17 @@ +config['info']; + } // client must enter at least `contact.email` to generate a default `info` block // otherwise an exception will be called if (!empty($this->config['info']) && !Arr::get($this->config, 'info.contact.email')) { @@ -149,7 +152,7 @@ protected function generateEmptyData(): array 'components' => [ 'schemas' => $this->config['definitions'], ], - 'info' => $this->prepareInfo($this->config['info']) + 'info' => $this->prepareInfo($info, $decriptionData), ]; $securityDefinitions = $this->generateSecurityDefinition(); @@ -837,14 +840,10 @@ public function getDocFileContent() $this->openAPIValidator->validate($documentation); } catch (Exception $exception) { - $data = $this->generateBaseDataObject(); - $infoConfig = $this->config['info']; $infoConfig['description'] = Arr::get($this->config, 'defaults.error'); - $data['info'] = $this->prepareInfo($infoConfig, ['message' => $exception->getMessage()]); - - return $data; + return $this->generateEmptyData($infoConfig, ['message' => $exception->getMessage()]); } $additionalDocs = config('auto-doc.additional_paths', []); From 72b9f873c50a8b0ab897a2102fa9e8202377e7ac Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Wed, 14 May 2025 14:25:27 +0300 Subject: [PATCH 07/19] refactor: set properties in preapareInfo --- src/Exceptions/FileNotFoundException.php | 8 +- src/Services/SwaggerService.php | 67 +++++------ tests/LocalDriverTest.php | 4 +- tests/RemoteDriverTest.php | 4 +- tests/StorageDriverTest.php | 6 +- tests/SwaggerServiceTest.php | 112 +++++++----------- ...valid_format_array_parameter_no_items.html | 1 + ...d_format_array_response_body_no_items.html | 1 + ...format_array_response_header_no_items.html | 1 + .../invalid_format_body_and_form_params.html | 1 + ...nvalid_format_duplicate_header_params.html | 1 + ...invalid_format_duplicate_operation_id.html | 1 + .../invalid_format_duplicate_path_params.html | 1 + ...id_format_duplicate_path_placeholders.html | 1 + .../invalid_format_duplicate_tag.html | 1 + .../invalid_format_file_invalid_consumes.html | 1 + .../invalid_format_file_no_consumes.html | 1 + .../invalid_format_invalid_schema_type.html | 1 + ...lid_format_invalid_value_parameter_in.html | 1 + .../invalid_format_invalid_value_path.html | 1 + ...alid_format_invalid_value_status_code.html | 1 + .../invalid_format_missing_external_ref.html | 1 + ..._format_missing_field_definition_type.html | 1 + ...alid_format_missing_field_header_type.html | 1 + ...lid_format_missing_field_info_version.html | 1 + ...valid_format_missing_field_items_type.html | 1 + ...mat_missing_field_operation_responses.html | 1 + ...lid_format_missing_field_parameter_in.html | 1 + .../invalid_format_missing_field_paths.html | 1 + ...at_missing_field_response_description.html | 1 + ...invalid_format_missing_field_tag_name.html | 1 + .../invalid_format_missing_local_ref.html | 1 + ...invalid_format_missing_path_parameter.html | 1 + .../invalid_format_missing_ref_file.html | 1 + .../invalid_format_multiple_body_params.html | 1 + .../invalid_format_no_path_params.html | 1 + ...alid_format_path_param_no_placeholder.html | 1 + ...d_format_request_body_invalid_content.html | 1 + ...invalid_format_response_invalid_items.html | 1 + ...valid_format_security_definition_flow.html | 1 + ...invalid_format_security_definition_in.html | 1 + ...valid_format_security_definition_type.html | 1 + .../SwaggerServiceTest/invalid_version.html | 1 + 43 files changed, 120 insertions(+), 118 deletions(-) create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_array_parameter_no_items.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_array_response_body_no_items.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_array_response_header_no_items.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_body_and_form_params.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_header_params.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_operation_id.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_path_params.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_path_placeholders.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_tag.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_file_invalid_consumes.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_file_no_consumes.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_invalid_schema_type.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_parameter_in.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_path.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_status_code.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_external_ref.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_definition_type.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_header_type.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_info_version.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_items_type.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_operation_responses.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_parameter_in.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_paths.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_response_description.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_tag_name.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_local_ref.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_path_parameter.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_missing_ref_file.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_multiple_body_params.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_no_path_params.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_path_param_no_placeholder.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_request_body_invalid_content.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_response_invalid_items.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_flow.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_in.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_type.html create mode 100644 tests/fixtures/SwaggerServiceTest/invalid_version.html diff --git a/src/Exceptions/FileNotFoundException.php b/src/Exceptions/FileNotFoundException.php index 88a65a08..22e2bbd4 100644 --- a/src/Exceptions/FileNotFoundException.php +++ b/src/Exceptions/FileNotFoundException.php @@ -2,16 +2,12 @@ namespace RonasIT\AutoDoc\Exceptions; -use \Illuminate\Contracts\Filesystem\FileNotFoundException as BaseException; +use Illuminate\Contracts\Filesystem\FileNotFoundException as BaseException; class FileNotFoundException extends BaseException { public function __construct(string $filePath = null) { - $message = empty($filePath) - ? 'Documentation file not found' - : "Documentation file not found: {$filePath}"; - - parent::__construct($message); + parent::__construct("Documentation file not found: {$filePath}"); } } \ No newline at end of file diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index 8d0627d3..13064ea9 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -80,7 +80,9 @@ public function __construct(Container $container) $this->data = $this->driver->getProcessTmpData(); if (empty($this->data)) { - $this->data = $this->generateEmptyData(); + $this->data = empty($this->config['info']) + ? $this->generateEmptyData() + : $this->generateEmptyData($this->config['info']['description']); $this->driver->saveProcessTmpData($this->data); } @@ -103,7 +105,7 @@ protected function initConfig() throw new LegacyConfigException(); } - $documentationViewer = (string) Arr::get($this->config, 'documentation_viewer'); + $documentationViewer = (string)Arr::get($this->config, 'documentation_viewer'); if (!view()->exists("auto-doc::documentation-{$documentationViewer}")) { throw new UnsupportedDocumentationViewerException($documentationViewer); @@ -132,11 +134,8 @@ protected function setDriver() } } - protected function generateEmptyData(array $info = [], $decriptionData = []): array + protected function generateEmptyData(?string $view = null, array $viewData = [], array $license = []): array { - if(empty($info)){ - $info = $this->config['info']; - } // client must enter at least `contact.email` to generate a default `info` block // otherwise an exception will be called if (!empty($this->config['info']) && !Arr::get($this->config, 'info.contact.email')) { @@ -152,7 +151,7 @@ protected function generateEmptyData(array $info = [], $decriptionData = []): ar 'components' => [ 'schemas' => $this->config['definitions'], ], - 'info' => $this->prepareInfo($info, $decriptionData), + 'info' =>$this->prepareInfo($view, $viewData, $license), ]; $securityDefinitions = $this->generateSecurityDefinition(); @@ -164,20 +163,6 @@ protected function generateEmptyData(array $info = [], $decriptionData = []): ar return $data; } - protected function generateBaseDataObject(): array - { - return [ - 'openapi' => self::OPEN_API_VERSION, - 'servers' => [ - ['url' => URL::query($this->config['basePath'])], - ], - 'paths' => [], - 'components' => [ - 'schemas' => $this->config['definitions'], - ], - ]; - } - protected function generateSecurityDefinition(): ?array { if (empty($this->security)) { @@ -278,7 +263,7 @@ protected function generatePathDescription(string $key): string foreach ($exploded as $value) { if (!preg_match('/^[a-zA-Z0-9\.]+$/', $value)) { - return "regexp: {$expression}"; + return "regexp: {$expression}"; } } @@ -614,8 +599,13 @@ protected function saveParameterType(&$data, $parameter, $parameterType) ]; } - protected function saveParameterDescription(&$data, $parameter, array $rulesArray, array $attributes, array $annotations) - { + protected function saveParameterDescription( + &$data, + $parameter, + array $rulesArray, + array $attributes, + array $annotations + ) { $description = Arr::get($annotations, $parameter); if (empty($description)) { @@ -821,7 +811,10 @@ public function saveProductionData() if (ParallelTesting::token()) { $this->driver->appendProcessDataToTmpFile(function (array $sharedTmpData) { $resultDocContent = (empty($sharedTmpData)) - ? $this->generateEmptyData() + ? $this->data = $this->generateEmptyData( + view: $this->config['info']['description'], + license: $this->config['info']['license'], + ) : $sharedTmpData; $this->mergeOpenAPIDocs($resultDocContent, $this->data); @@ -843,7 +836,7 @@ public function getDocFileContent() $infoConfig = $this->config['info']; $infoConfig['description'] = Arr::get($this->config, 'defaults.error'); - return $this->generateEmptyData($infoConfig, ['message' => $exception->getMessage()]); + return $this->generateEmptyData($this->config['defaults']['error'], ['message' => $exception->getMessage()]); } $additionalDocs = config('auto-doc.additional_paths', []); @@ -971,27 +964,27 @@ protected function getDefaultValueByType($type) return $values[$type]; } - protected function prepareInfo(array $info, array $descriptionData = []): array + protected function prepareInfo(?string $view = null, array $viewData = [], array $license = []): array { - if (empty($info)) { - return $info; - } + $info = []; - foreach ($info['license'] as $key => $value) { + foreach ($license as $key => $value) { if (empty($value)) { - unset($info['license'][$key]); + unset($license[$key]); } } - if (empty($info['license'])) { - unset($info['license']); + if (!empty($license)) { + $info['license'] = $license; } - if (!empty($info['description'])) { - $info['description'] = view($info['description'], $descriptionData)->render(); + if (!empty($view)) { + $info['description'] = view($view, $viewData)->render(); } - return $info; + $infoConfig = Arr::except($this->config['info'], ['description', 'license']); + + return array_merge($info, $infoConfig); } protected function getOpenAPIFileContent(string $filePath): array diff --git a/tests/LocalDriverTest.php b/tests/LocalDriverTest.php index 07c183b1..05a24643 100755 --- a/tests/LocalDriverTest.php +++ b/tests/LocalDriverTest.php @@ -3,7 +3,7 @@ namespace RonasIT\AutoDoc\Tests; use RonasIT\AutoDoc\Drivers\LocalDriver; -use Illuminate\Contracts\Filesystem\FileNotFoundException; +use RonasIT\AutoDoc\Exceptions\FileNotFoundException; use RonasIT\AutoDoc\Exceptions\MissedProductionFilePathException; class LocalDriverTest extends TestCase @@ -128,6 +128,8 @@ public function testGetDocumentationFileNotExists() { $this->expectException(FileNotFoundException::class); + $this->expectExceptionMessage('Documentation file not found: '.config(['auto-doc.drivers.local.production_path'])); + config(['auto-doc.drivers.local.production_path' => 'not_exists_file']); (new LocalDriver())->getDocumentation(); diff --git a/tests/RemoteDriverTest.php b/tests/RemoteDriverTest.php index 2acea917..d825cf6d 100755 --- a/tests/RemoteDriverTest.php +++ b/tests/RemoteDriverTest.php @@ -4,7 +4,7 @@ use RonasIT\AutoDoc\Drivers\RemoteDriver; use RonasIT\AutoDoc\Exceptions\MissedRemoteDocumentationUrlException; -use Illuminate\Contracts\Filesystem\FileNotFoundException; +use RonasIT\AutoDoc\Exceptions\FileNotFoundException; use RonasIT\Support\Traits\MockTrait; class RemoteDriverTest extends TestCase @@ -153,6 +153,8 @@ public function testGetDocumentationNoFile() { $this->expectException(FileNotFoundException::class); + $this->expectExceptionMessage('Docum entation file not found:'); + config(['auto-doc.drivers.remote.key' => 'mocked_key']); config(['auto-doc.drivers.remote.url' => 'mocked_url']); diff --git a/tests/StorageDriverTest.php b/tests/StorageDriverTest.php index 0453b917..7ef87f6d 100755 --- a/tests/StorageDriverTest.php +++ b/tests/StorageDriverTest.php @@ -2,7 +2,7 @@ namespace RonasIT\AutoDoc\Tests; -use Illuminate\Contracts\Filesystem\FileNotFoundException; +use RonasIT\AutoDoc\Exceptions\FileNotFoundException; use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Support\Facades\Storage; use RonasIT\AutoDoc\Drivers\StorageDriver; @@ -110,7 +110,7 @@ public function testSaveData() } public function testGetDocumentation() - { + { $this->disk->put(self::$productionFilePath, $this->getFixture('tmp_data_non_formatted.json')); $documentation = self::$storageDriverClass->getDocumentation(); @@ -122,6 +122,8 @@ public function testGetDocumentationFileNotExists() { $this->expectException(FileNotFoundException::class); + $this->expectExceptionMessage('Documentation file not found:'); + self::$storageDriverClass->getDocumentation(); } } diff --git a/tests/SwaggerServiceTest.php b/tests/SwaggerServiceTest.php index ce934bab..5d6ff7d2 100644 --- a/tests/SwaggerServiceTest.php +++ b/tests/SwaggerServiceTest.php @@ -77,179 +77,151 @@ public static function getConstructorInvalidTmpData(): array return [ [ 'tmpDoc' => 'documentation/invalid_version', - 'exceptionMessage' => "Validation failed. Unrecognized Swagger version '1.0'. Expected 3.1.0.", + 'fixture' => 'invalid_version.html', ], [ 'tmpDoc' => 'documentation/invalid_format__array_parameter__no_items', - 'exceptionMessage' => "Validation failed. paths./users.post.parameters.0 is an " - . "array, so it must include an 'items' field.", + 'fixture' => 'invalid_format_array_parameter_no_items.html', ], [ 'tmpDoc' => 'documentation/invalid_format__array_response_body__no_items', - 'exceptionMessage' => "Validation failed. paths./users.get.responses.200.schema is an array, " - . "so it must include an 'items' field.", + 'fixture' => 'invalid_format_array_response_body_no_items.html', ], [ 'tmpDoc' => 'documentation/invalid_format__array_response_header__no_items', - 'exceptionMessage' => "Validation failed. paths./users.get.responses.default.headers." - . "Last-Modified is an array, so it must include an 'items' field.", + 'fixture' => 'invalid_format_array_response_header_no_items.html', ], [ 'tmpDoc' => 'documentation/invalid_format__body_and_form_params', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.post' " - . "has body and formData parameters. Only one or the other is allowed.", + 'fixture' => 'invalid_format_body_and_form_params.html', ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_header_params', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.get' " - . "has multiple in:header parameters with name:foo.", + 'fixture' => 'invalid_format_duplicate_header_params.html', ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_path_params', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.get' has " - . "multiple in:path parameters with name:username.", + 'fixture' => 'invalid_format_duplicate_path_params.html', ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_path_placeholders', - 'exceptionMessage' => "Validation failed. Path '/users/{username}/profile/{username}/image/{img_id}' " - . "has multiple path placeholders with name: username.", + 'fixture' => 'invalid_format_duplicate_path_placeholders.html', ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_operation_id', - 'exceptionMessage' => "Validation failed. Found multiple fields 'paths.*.*.operationId' " - . "with values: addPet.", + 'fixture' => 'invalid_format_duplicate_operation_id.html', ], [ 'tmpDoc' => 'documentation/invalid_format__duplicate_tag', - 'exceptionMessage' => "Validation failed. Found multiple fields 'tags.*.name' with values: user.", + 'fixture' => 'invalid_format_duplicate_tag.html', ], [ 'tmpDoc' => 'documentation/invalid_format__file_invalid_consumes', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}/profile/image.post' " - . "has body and formData parameters. Only one or the other is allowed.", + 'fixture' => 'invalid_format_file_invalid_consumes.html', ], [ 'tmpDoc' => 'documentation/invalid_format__file_no_consumes', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}/profile/image.post' " - . "has body and formData parameters. Only one or the other is allowed.", + 'fixture' => 'invalid_format_file_no_consumes.html', ], [ 'tmpDoc' => 'documentation/invalid_format__multiple_body_params', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.get' has 2 body " - . "parameters. Only one is allowed.", + 'fixture' => 'invalid_format_multiple_body_params.html', ], [ 'tmpDoc' => 'documentation/invalid_format__no_path_params', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}/{foo}.get' has " - . "no params for placeholders: username, foo.", + 'fixture' => 'invalid_format_no_path_params.html', ], [ 'tmpDoc' => 'documentation/invalid_format__path_param_no_placeholder', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{username}.post' has no " - . "placeholders for params: foo.", + 'fixture' => 'invalid_format_path_param_no_placeholder.html', ], [ 'tmpDoc' => 'documentation/invalid_format__invalid_value__path', - 'exceptionMessage' => "Validation failed. Incorrect 'paths.users'. Paths should only have path " - . "names that starts with `/`.", + 'fixture' => 'invalid_format_invalid_value_path.html', ], [ 'tmpDoc' => 'documentation/invalid_format__invalid_value__status_code', - 'exceptionMessage' => "Validation failed. Operation at 'paths./users.get.responses.8888' should " - . "only have three-digit status codes, `default`, and vendor extensions (`x-*`) as properties.", + 'fixture' => 'invalid_format_invalid_value_status_code.html', ], [ 'tmpDoc' => 'documentation/invalid_format__invalid_value__parameter_in', - 'exceptionMessage' => "Validation failed. Field 'paths./auth/login.post.parameters.0.in' " - . "has an invalid value: invalid_in. Allowed values: body, formData, query, path, header.", + 'fixture' => 'invalid_format_invalid_value_parameter_in.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__paths', - 'exceptionMessage' => "Validation failed. '' should have required fields: paths.", + 'fixture' => 'invalid_format_missing_field_paths.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__operation_responses', - 'exceptionMessage' => "Validation failed. 'paths./auth/login.post' should have required " - . "fields: responses.", + 'fixture' => 'invalid_format_missing_field_operation_responses.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__parameter_in', - 'exceptionMessage' => "Validation failed. 'paths./auth/login.post.parameters.0' should " - . "have required fields: in.", + 'fixture' => 'invalid_format_missing_field_parameter_in.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__response_description', - 'exceptionMessage' => "Validation failed. 'paths./auth/login.post.responses.200' should " - . "have required fields: description.", + 'fixture' => 'invalid_format_missing_field_response_description.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__definition_type', - 'exceptionMessage' => "Validation failed. 'components.schemas.authloginObject' should have " - . "required fields: type.", + 'fixture' => 'invalid_format_missing_field_definition_type.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__info_version', - 'exceptionMessage' => "Validation failed. 'info' should have required fields: version.", + 'fixture' => 'invalid_format_missing_field_info_version.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__items_type', - 'exceptionMessage' => "Validation failed. 'paths./pet/findByStatus.get.parameters.0.schema.items' " - . "should have required fields: type.", + 'fixture' => 'invalid_format_missing_field_items_type.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__header_type', - 'exceptionMessage' => "Validation failed. 'paths./user/login.get.responses.200.headers.X-Rate-Limit' " - . "should have required fields: type.", + 'fixture' => 'invalid_format_missing_field_header_type.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_field__tag_name', - 'exceptionMessage' => "Validation failed. 'tags.0' should have required fields: name.", + 'fixture' => 'invalid_format_missing_field_tag_name.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_local_ref', - 'exceptionMessage' => "Validation failed. Ref 'loginObject' is used in \$ref but not defined " - . "in 'definitions' field.", + 'fixture' => 'invalid_format_missing_local_ref.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_external_ref', - 'exceptionMessage' => "Validation failed. Ref 'authloginObject' is used in \$ref but not defined " - . "in 'tests/fixtures/SwaggerServiceTest/documentation/with_definitions.json' file.", + 'fixture' => 'invalid_format_missing_external_ref.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_ref_file', - 'exceptionMessage' => "Validation failed. Filename 'invalid-filename.json' is used in \$ref but " - . "file doesn't exist.", + 'fixture' => 'invalid_format_missing_ref_file.html', ], [ 'tmpDoc' => 'documentation/invalid_format__invalid_schema_type', - 'exceptionMessage' => "Validation failed. Field 'paths./users.get.responses.200.schema.type' " - . "has an invalid value: something. Allowed values: array, boolean, integer, number, " - . "string, object, null, undefined, file.", + 'fixture' => 'invalid_format_invalid_schema_type.html', ], [ 'tmpDoc' => 'documentation/invalid_format__missing_path_parameter', - 'exceptionMessage' => "Validation failed. Path parameters cannot be optional. " - . "Set required=true for the 'username' parameters at operation 'paths./users.get'.", + 'fixture' => 'invalid_format_missing_path_parameter.html', ], [ 'tmpDoc' => 'documentation/invalid_format__security_definition__type', - 'exceptionMessage' => "Validation failed. Field 'securityDefinitions.0.type' has an invalid value: invalid. Allowed values: basic, apiKey, oauth2.", + 'fixture' => 'invalid_format_security_definition_type.html', ], [ 'tmpDoc' => 'documentation/invalid_format__security_definition__flow', - 'exceptionMessage' => "Validation failed. Field 'securityDefinitions.0.flow' has an invalid value: invalid. Allowed values: implicit, password, application, accessCode.", + 'fixture' => 'invalid_format_security_definition_flow.html', ], [ 'tmpDoc' => 'documentation/invalid_format__security_definition__in', - 'exceptionMessage' => "Validation failed. Field 'securityDefinitions.0.in' has an invalid value: invalid. Allowed values: query, header.", + 'fixture' => 'invalid_format_security_definition_in.html', ], [ 'tmpDoc' => 'documentation/invalid_format__request_body__invalid_content', - 'exceptionMessage' => "Validation failed. Operation 'paths./users/{id}.post' has invalid content types: image/png.", + 'fixture' => 'invalid_format_request_body_invalid_content.html', ], [ 'tmpDoc' => 'documentation/invalid_format__response__invalid_items', - 'exceptionMessage' => "Validation failed. 'paths./users/{id}.post.responses.200.schema.items' should have required fields: type.", + 'fixture' => 'invalid_format_response_invalid_items.html', ], ]; } @@ -257,17 +229,15 @@ public static function getConstructorInvalidTmpData(): array #[DataProvider('getConstructorInvalidTmpData')] public function testGetDocFileContentInvalidTmpData( string $tmpDoc, - string $exceptionMessage, + string $fixture, ) { $this->mockDriverGetDocumentation($this->getJsonFixture($tmpDoc)); - app(SwaggerService::class)->getDocFileContent(); - + $content = app(SwaggerService::class)->getDocFileContent(); + View::addLocation(__DIR__ . '/../resources/views'); - $rendered = view('error', ['message' => $exceptionMessage])->render(); - - $this->assertStringContainsString($exceptionMessage, html_entity_decode($rendered)); + $this->assertEqualsFixture($fixture, $content['info']['description']); } public function testEmptyContactEmail() diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_array_parameter_no_items.html b/tests/fixtures/SwaggerServiceTest/invalid_format_array_parameter_no_items.html new file mode 100644 index 00000000..5ee5a195 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_array_parameter_no_items.html @@ -0,0 +1 @@ +Validation failed. paths./users.post.parameters.0 is an array, so it must include an 'items' field. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_array_response_body_no_items.html b/tests/fixtures/SwaggerServiceTest/invalid_format_array_response_body_no_items.html new file mode 100644 index 00000000..daf4fee1 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_array_response_body_no_items.html @@ -0,0 +1 @@ +Validation failed. paths./users.get.responses.200.schema is an array, so it must include an 'items' field. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_array_response_header_no_items.html b/tests/fixtures/SwaggerServiceTest/invalid_format_array_response_header_no_items.html new file mode 100644 index 00000000..caf830c0 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_array_response_header_no_items.html @@ -0,0 +1 @@ +Validation failed. paths./users.get.responses.default.headers.Last-Modified is an array, so it must include an 'items' field. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_body_and_form_params.html b/tests/fixtures/SwaggerServiceTest/invalid_format_body_and_form_params.html new file mode 100644 index 00000000..389e03a0 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_body_and_form_params.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{username}.post' has body and formData parameters. Only one or the other is allowed. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_header_params.html b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_header_params.html new file mode 100644 index 00000000..0a770041 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_header_params.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{username}.get' has multiple in:header parameters with name:foo. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_operation_id.html b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_operation_id.html new file mode 100644 index 00000000..25dbb9bc --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_operation_id.html @@ -0,0 +1 @@ +Validation failed. Found multiple fields 'paths.*.*.operationId' with values: addPet. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_path_params.html b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_path_params.html new file mode 100644 index 00000000..a03ed69e --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_path_params.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{username}.get' has multiple in:path parameters with name:username. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_path_placeholders.html b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_path_placeholders.html new file mode 100644 index 00000000..5e443501 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_path_placeholders.html @@ -0,0 +1 @@ +Validation failed. Path '/users/{username}/profile/{username}/image/{img_id}' has multiple path placeholders with name: username. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_tag.html b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_tag.html new file mode 100644 index 00000000..99344580 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_duplicate_tag.html @@ -0,0 +1 @@ +Validation failed. Found multiple fields 'tags.*.name' with values: user. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_file_invalid_consumes.html b/tests/fixtures/SwaggerServiceTest/invalid_format_file_invalid_consumes.html new file mode 100644 index 00000000..22b966e5 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_file_invalid_consumes.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{username}/profile/image.post' has body and formData parameters. Only one or the other is allowed. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_file_no_consumes.html b/tests/fixtures/SwaggerServiceTest/invalid_format_file_no_consumes.html new file mode 100644 index 00000000..22b966e5 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_file_no_consumes.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{username}/profile/image.post' has body and formData parameters. Only one or the other is allowed. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_schema_type.html b/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_schema_type.html new file mode 100644 index 00000000..a6c49ec3 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_schema_type.html @@ -0,0 +1 @@ +Validation failed. Field 'paths./users.get.responses.200.schema.type' has an invalid value: something. Allowed values: array, boolean, integer, number, string, object, null, undefined, file. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_parameter_in.html b/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_parameter_in.html new file mode 100644 index 00000000..68a11aac --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_parameter_in.html @@ -0,0 +1 @@ +Validation failed. Field 'paths./auth/login.post.parameters.0.in' has an invalid value: invalid_in. Allowed values: body, formData, query, path, header. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_path.html b/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_path.html new file mode 100644 index 00000000..96de275c --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_path.html @@ -0,0 +1 @@ +Validation failed. Incorrect 'paths.users'. Paths should only have path names that starts with `/`. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_status_code.html b/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_status_code.html new file mode 100644 index 00000000..07d68cac --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_invalid_value_status_code.html @@ -0,0 +1 @@ +Validation failed. Operation at 'paths./users.get.responses.8888' should only have three-digit status codes, `default`, and vendor extensions (`x-*`) as properties. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_external_ref.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_external_ref.html new file mode 100644 index 00000000..2eace1cf --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_external_ref.html @@ -0,0 +1 @@ +Validation failed. Ref 'authloginObject' is used in $ref but not defined in 'tests/fixtures/SwaggerServiceTest/documentation/with_definitions.json' file. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_definition_type.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_definition_type.html new file mode 100644 index 00000000..e2bd233c --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_definition_type.html @@ -0,0 +1 @@ +Validation failed. 'components.schemas.authloginObject' should have required fields: type. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_header_type.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_header_type.html new file mode 100644 index 00000000..28a5c4ff --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_header_type.html @@ -0,0 +1 @@ +Validation failed. 'paths./user/login.get.responses.200.headers.X-Rate-Limit' should have required fields: type. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_info_version.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_info_version.html new file mode 100644 index 00000000..dc3dac19 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_info_version.html @@ -0,0 +1 @@ +Validation failed. 'info' should have required fields: version. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_items_type.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_items_type.html new file mode 100644 index 00000000..0e470070 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_items_type.html @@ -0,0 +1 @@ +Validation failed. 'paths./pet/findByStatus.get.parameters.0.schema.items' should have required fields: type. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_operation_responses.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_operation_responses.html new file mode 100644 index 00000000..5ebd060b --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_operation_responses.html @@ -0,0 +1 @@ +Validation failed. 'paths./auth/login.post' should have required fields: responses. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_parameter_in.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_parameter_in.html new file mode 100644 index 00000000..996315fa --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_parameter_in.html @@ -0,0 +1 @@ +Validation failed. 'paths./auth/login.post.parameters.0' should have required fields: in. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_paths.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_paths.html new file mode 100644 index 00000000..c68f537e --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_paths.html @@ -0,0 +1 @@ +Validation failed. '' should have required fields: paths. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_response_description.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_response_description.html new file mode 100644 index 00000000..c272c3d5 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_response_description.html @@ -0,0 +1 @@ +Validation failed. 'paths./auth/login.post.responses.200' should have required fields: description. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_tag_name.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_tag_name.html new file mode 100644 index 00000000..54dece06 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_field_tag_name.html @@ -0,0 +1 @@ +Validation failed. 'tags.0' should have required fields: name. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_local_ref.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_local_ref.html new file mode 100644 index 00000000..13d8fc9a --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_local_ref.html @@ -0,0 +1 @@ +Validation failed. Ref 'loginObject' is used in $ref but not defined in 'definitions' field. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_path_parameter.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_path_parameter.html new file mode 100644 index 00000000..46a71416 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_path_parameter.html @@ -0,0 +1 @@ +Validation failed. Path parameters cannot be optional. Set required=true for the 'username' parameters at operation 'paths./users.get'. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_missing_ref_file.html b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_ref_file.html new file mode 100644 index 00000000..a7794cf8 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_missing_ref_file.html @@ -0,0 +1 @@ +Validation failed. Filename 'invalid-filename.json' is used in $ref but file doesn't exist. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_multiple_body_params.html b/tests/fixtures/SwaggerServiceTest/invalid_format_multiple_body_params.html new file mode 100644 index 00000000..3eaab7d4 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_multiple_body_params.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{username}.get' has 2 body parameters. Only one is allowed. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_no_path_params.html b/tests/fixtures/SwaggerServiceTest/invalid_format_no_path_params.html new file mode 100644 index 00000000..543b42ff --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_no_path_params.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{username}/{foo}.get' has no params for placeholders: username, foo. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_path_param_no_placeholder.html b/tests/fixtures/SwaggerServiceTest/invalid_format_path_param_no_placeholder.html new file mode 100644 index 00000000..1e350309 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_path_param_no_placeholder.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{username}.post' has no placeholders for params: foo. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_request_body_invalid_content.html b/tests/fixtures/SwaggerServiceTest/invalid_format_request_body_invalid_content.html new file mode 100644 index 00000000..0884fddc --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_request_body_invalid_content.html @@ -0,0 +1 @@ +Validation failed. Operation 'paths./users/{id}.post' has invalid content types: image/png. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_response_invalid_items.html b/tests/fixtures/SwaggerServiceTest/invalid_format_response_invalid_items.html new file mode 100644 index 00000000..8e42aa1f --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_response_invalid_items.html @@ -0,0 +1 @@ +Validation failed. 'paths./users/{id}.post.responses.200.schema.items' should have required fields: type. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_flow.html b/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_flow.html new file mode 100644 index 00000000..3e0fc9b6 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_flow.html @@ -0,0 +1 @@ +Validation failed. Field 'securityDefinitions.0.flow' has an invalid value: invalid. Allowed values: implicit, password, application, accessCode. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_in.html b/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_in.html new file mode 100644 index 00000000..241f6946 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_in.html @@ -0,0 +1 @@ +Validation failed. Field 'securityDefinitions.0.in' has an invalid value: invalid. Allowed values: query, header. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_type.html b/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_type.html new file mode 100644 index 00000000..33a2c0a9 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_format_security_definition_type.html @@ -0,0 +1 @@ +Validation failed. Field 'securityDefinitions.0.type' has an invalid value: invalid. Allowed values: basic, apiKey, oauth2. \ No newline at end of file diff --git a/tests/fixtures/SwaggerServiceTest/invalid_version.html b/tests/fixtures/SwaggerServiceTest/invalid_version.html new file mode 100644 index 00000000..581fef92 --- /dev/null +++ b/tests/fixtures/SwaggerServiceTest/invalid_version.html @@ -0,0 +1 @@ +Validation failed. Unrecognized Swagger version '1.0'. Expected 3.1.0. \ No newline at end of file From f8488c132ea611fd6711e93d14030f09a570def6 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Wed, 14 May 2025 14:33:11 +0300 Subject: [PATCH 08/19] style:add empty spaces --- src/Services/SwaggerService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index 13064ea9..de099301 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -105,7 +105,7 @@ protected function initConfig() throw new LegacyConfigException(); } - $documentationViewer = (string)Arr::get($this->config, 'documentation_viewer'); + $documentationViewer = (string) Arr::get($this->config, 'documentation_viewer'); if (!view()->exists("auto-doc::documentation-{$documentationViewer}")) { throw new UnsupportedDocumentationViewerException($documentationViewer); @@ -151,7 +151,7 @@ protected function generateEmptyData(?string $view = null, array $viewData = [], 'components' => [ 'schemas' => $this->config['definitions'], ], - 'info' =>$this->prepareInfo($view, $viewData, $license), + 'info' => $this->prepareInfo($view, $viewData, $license), ]; $securityDefinitions = $this->generateSecurityDefinition(); From 765ecfbf6b9d002d45d3e55e058e6547f8c34065 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Wed, 14 May 2025 14:35:47 +0300 Subject: [PATCH 09/19] fix:tests --- tests/RemoteDriverTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/RemoteDriverTest.php b/tests/RemoteDriverTest.php index d825cf6d..7a42bc08 100755 --- a/tests/RemoteDriverTest.php +++ b/tests/RemoteDriverTest.php @@ -153,7 +153,7 @@ public function testGetDocumentationNoFile() { $this->expectException(FileNotFoundException::class); - $this->expectExceptionMessage('Docum entation file not found:'); + $this->expectExceptionMessage('Documentation file not found:'); config(['auto-doc.drivers.remote.key' => 'mocked_key']); config(['auto-doc.drivers.remote.url' => 'mocked_url']); From 5bd1f900da22dc3db8ef9d78d1e06688228b7cbb Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Wed, 14 May 2025 14:46:56 +0300 Subject: [PATCH 10/19] style: fix braces position --- tests/StorageDriverTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/StorageDriverTest.php b/tests/StorageDriverTest.php index 7ef87f6d..7d8eb053 100755 --- a/tests/StorageDriverTest.php +++ b/tests/StorageDriverTest.php @@ -110,7 +110,7 @@ public function testSaveData() } public function testGetDocumentation() - { + { $this->disk->put(self::$productionFilePath, $this->getFixture('tmp_data_non_formatted.json')); $documentation = self::$storageDriverClass->getDocumentation(); From ebaad2343efa3b6fdbc849a78ab853aa5959cd92 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Wed, 14 May 2025 14:48:07 +0300 Subject: [PATCH 11/19] fix: remove useless import --- tests/SwaggerServiceTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/SwaggerServiceTest.php b/tests/SwaggerServiceTest.php index 5d6ff7d2..bd6bc03d 100644 --- a/tests/SwaggerServiceTest.php +++ b/tests/SwaggerServiceTest.php @@ -3,7 +3,6 @@ namespace RonasIT\AutoDoc\Tests; use Illuminate\Http\Testing\File; -use Illuminate\Support\Facades\View; use PHPUnit\Framework\Attributes\DataProvider; use RonasIT\AutoDoc\Exceptions\EmptyContactEmailException; use RonasIT\AutoDoc\Exceptions\InvalidDriverClassException; @@ -234,8 +233,6 @@ public function testGetDocFileContentInvalidTmpData( $this->mockDriverGetDocumentation($this->getJsonFixture($tmpDoc)); $content = app(SwaggerService::class)->getDocFileContent(); - - View::addLocation(__DIR__ . '/../resources/views'); $this->assertEqualsFixture($fixture, $content['info']['description']); } From f35b440ecea8465b3f662947c8b00d14eec988e7 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Wed, 14 May 2025 14:54:47 +0300 Subject: [PATCH 12/19] style: remove useless multiline --- src/Services/SwaggerService.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index de099301..7047cd14 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -811,10 +811,7 @@ public function saveProductionData() if (ParallelTesting::token()) { $this->driver->appendProcessDataToTmpFile(function (array $sharedTmpData) { $resultDocContent = (empty($sharedTmpData)) - ? $this->data = $this->generateEmptyData( - view: $this->config['info']['description'], - license: $this->config['info']['license'], - ) + ? $this->data = $this->generateEmptyData($this->config['info']['description']) : $sharedTmpData; $this->mergeOpenAPIDocs($resultDocContent, $this->data); From 322c1739819326eaab15d1283554c339cb9b9c3e Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Thu, 15 May 2025 12:56:43 +0300 Subject: [PATCH 13/19] fix: assertExceptionMessage check --- src/Drivers/RemoteDriver.php | 2 +- src/Exceptions/FileNotFoundException.php | 2 +- src/Services/SwaggerService.php | 21 ++++++++------------- tests/LocalDriverTest.php | 2 +- tests/RemoteDriverTest.php | 2 +- tests/StorageDriverTest.php | 2 +- 6 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/Drivers/RemoteDriver.php b/src/Drivers/RemoteDriver.php index db5e6e7f..34792410 100755 --- a/src/Drivers/RemoteDriver.php +++ b/src/Drivers/RemoteDriver.php @@ -36,7 +36,7 @@ public function getDocumentation(): array list($content, $statusCode) = $this->makeHttpRequest('get', $this->getUrl()); if (empty($content) || $statusCode !== 200) { - throw new FileNotFoundException('Documentation file not found.'); + throw new FileNotFoundException(); } return json_decode($content, true); diff --git a/src/Exceptions/FileNotFoundException.php b/src/Exceptions/FileNotFoundException.php index 22e2bbd4..84a896c5 100644 --- a/src/Exceptions/FileNotFoundException.php +++ b/src/Exceptions/FileNotFoundException.php @@ -8,6 +8,6 @@ class FileNotFoundException extends BaseException { public function __construct(string $filePath = null) { - parent::__construct("Documentation file not found: {$filePath}"); + parent::__construct("Documentation file not found {$filePath}"); } } \ No newline at end of file diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index 7047cd14..a8c56d45 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -80,9 +80,7 @@ public function __construct(Container $container) $this->data = $this->driver->getProcessTmpData(); if (empty($this->data)) { - $this->data = empty($this->config['info']) - ? $this->generateEmptyData() - : $this->generateEmptyData($this->config['info']['description']); + $this->data = $this->generateEmptyData(); $this->driver->saveProcessTmpData($this->data); } @@ -142,6 +140,10 @@ protected function generateEmptyData(?string $view = null, array $viewData = [], throw new EmptyContactEmailException(); } + if(empty($view) && !empty($this->config['info'])){ + $view = $this->config['info']['description']; + } + $data = [ 'openapi' => self::OPEN_API_VERSION, 'servers' => [ @@ -811,7 +813,7 @@ public function saveProductionData() if (ParallelTesting::token()) { $this->driver->appendProcessDataToTmpFile(function (array $sharedTmpData) { $resultDocContent = (empty($sharedTmpData)) - ? $this->data = $this->generateEmptyData($this->config['info']['description']) + ? $this->generateEmptyData($this->config['info']['description']) : $sharedTmpData; $this->mergeOpenAPIDocs($resultDocContent, $this->data); @@ -830,9 +832,6 @@ public function getDocFileContent() $this->openAPIValidator->validate($documentation); } catch (Exception $exception) { - $infoConfig = $this->config['info']; - $infoConfig['description'] = Arr::get($this->config, 'defaults.error'); - return $this->generateEmptyData($this->config['defaults']['error'], ['message' => $exception->getMessage()]); } @@ -965,11 +964,7 @@ protected function prepareInfo(?string $view = null, array $viewData = [], array { $info = []; - foreach ($license as $key => $value) { - if (empty($value)) { - unset($license[$key]); - } - } + $license = array_filter($license, fn($value) => !empty($value)); if (!empty($license)) { $info['license'] = $license; @@ -981,7 +976,7 @@ protected function prepareInfo(?string $view = null, array $viewData = [], array $infoConfig = Arr::except($this->config['info'], ['description', 'license']); - return array_merge($info, $infoConfig); + return array_merge($infoConfig, $info); } protected function getOpenAPIFileContent(string $filePath): array diff --git a/tests/LocalDriverTest.php b/tests/LocalDriverTest.php index 05a24643..91de1fec 100755 --- a/tests/LocalDriverTest.php +++ b/tests/LocalDriverTest.php @@ -128,7 +128,7 @@ public function testGetDocumentationFileNotExists() { $this->expectException(FileNotFoundException::class); - $this->expectExceptionMessage('Documentation file not found: '.config(['auto-doc.drivers.local.production_path'])); + $this->expectExceptionMessageMatches('/^Documentation file not found not_exists_file$/'); config(['auto-doc.drivers.local.production_path' => 'not_exists_file']); diff --git a/tests/RemoteDriverTest.php b/tests/RemoteDriverTest.php index 7a42bc08..2675e155 100755 --- a/tests/RemoteDriverTest.php +++ b/tests/RemoteDriverTest.php @@ -153,7 +153,7 @@ public function testGetDocumentationNoFile() { $this->expectException(FileNotFoundException::class); - $this->expectExceptionMessage('Documentation file not found:'); + $this->expectExceptionMessageMatches('/^Documentation file not found $/'); config(['auto-doc.drivers.remote.key' => 'mocked_key']); config(['auto-doc.drivers.remote.url' => 'mocked_url']); diff --git a/tests/StorageDriverTest.php b/tests/StorageDriverTest.php index 7d8eb053..77160144 100755 --- a/tests/StorageDriverTest.php +++ b/tests/StorageDriverTest.php @@ -122,7 +122,7 @@ public function testGetDocumentationFileNotExists() { $this->expectException(FileNotFoundException::class); - $this->expectExceptionMessage('Documentation file not found:'); + $this->expectExceptionMessageMatches('/^Documentation file not found documentation.json$/'); self::$storageDriverClass->getDocumentation(); } From b2d06d2499259187e22b03a664f56bd2a57cd08f Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Tue, 27 May 2025 14:39:09 +0300 Subject: [PATCH 14/19] refactor: use TestingTrait from helpers --- composer.lock | 12 ++++++------ tests/AutoDocControllerTest.php | 2 -- tests/LocalDriverTest.php | 4 +--- tests/RemoteDriverTest.php | 7 +------ tests/StorageDriverTest.php | 4 +--- tests/TestCase.php | 3 ++- 6 files changed, 11 insertions(+), 21 deletions(-) diff --git a/composer.lock b/composer.lock index 3220d9f2..d72c2b74 100644 --- a/composer.lock +++ b/composer.lock @@ -9320,16 +9320,16 @@ }, { "name": "ronasit/laravel-helpers", - "version": "3.4.1", + "version": "3.4.2", "source": { "type": "git", "url": "https://github.com/RonasIT/laravel-helpers.git", - "reference": "997141b533877508e074263a1cf92fa1664816a9" + "reference": "287d5e3a3af61a34ae58efbd69d2780a935c5ab4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RonasIT/laravel-helpers/zipball/997141b533877508e074263a1cf92fa1664816a9", - "reference": "997141b533877508e074263a1cf92fa1664816a9", + "url": "https://api.github.com/repos/RonasIT/laravel-helpers/zipball/287d5e3a3af61a34ae58efbd69d2780a935c5ab4", + "reference": "287d5e3a3af61a34ae58efbd69d2780a935c5ab4", "shasum": "" }, "require": { @@ -9395,9 +9395,9 @@ ], "support": { "issues": "https://github.com/RonasIT/laravel-helpers/issues", - "source": "https://github.com/RonasIT/laravel-helpers/tree/3.4.1" + "source": "https://github.com/RonasIT/laravel-helpers/tree/3.4.2" }, - "time": "2025-04-30T14:00:55+00:00" + "time": "2025-05-26T03:41:09+00:00" }, { "name": "symfony/config", diff --git a/tests/AutoDocControllerTest.php b/tests/AutoDocControllerTest.php index ae21d3e1..cf9141d8 100644 --- a/tests/AutoDocControllerTest.php +++ b/tests/AutoDocControllerTest.php @@ -4,11 +4,9 @@ use Illuminate\Http\Response; use phpmock\phpunit\PHPMock; -use RonasIT\Support\Traits\MockTrait; class AutoDocControllerTest extends TestCase { - use MockTrait; use PHPMock; protected static array $documentation; diff --git a/tests/LocalDriverTest.php b/tests/LocalDriverTest.php index 91de1fec..bd599fcd 100755 --- a/tests/LocalDriverTest.php +++ b/tests/LocalDriverTest.php @@ -126,9 +126,7 @@ public function testGetDocumentation() public function testGetDocumentationFileNotExists() { - $this->expectException(FileNotFoundException::class); - - $this->expectExceptionMessageMatches('/^Documentation file not found not_exists_file$/'); + $this->assertExceptionThrew(FileNotFoundException::class, 'Documentation file not found not_exists_file'); config(['auto-doc.drivers.local.production_path' => 'not_exists_file']); diff --git a/tests/RemoteDriverTest.php b/tests/RemoteDriverTest.php index 2675e155..374ec6ca 100755 --- a/tests/RemoteDriverTest.php +++ b/tests/RemoteDriverTest.php @@ -5,12 +5,9 @@ use RonasIT\AutoDoc\Drivers\RemoteDriver; use RonasIT\AutoDoc\Exceptions\MissedRemoteDocumentationUrlException; use RonasIT\AutoDoc\Exceptions\FileNotFoundException; -use RonasIT\Support\Traits\MockTrait; class RemoteDriverTest extends TestCase { - use MockTrait; - protected static array $tmpData; protected static RemoteDriver $remoteDriverClass; protected static string $tmpDocumentationFilePath; @@ -151,9 +148,7 @@ public function testGetDocumentation() public function testGetDocumentationNoFile() { - $this->expectException(FileNotFoundException::class); - - $this->expectExceptionMessageMatches('/^Documentation file not found $/'); + $this->assertExceptionThrew(FileNotFoundException::class, 'Documentation file not found '); config(['auto-doc.drivers.remote.key' => 'mocked_key']); config(['auto-doc.drivers.remote.url' => 'mocked_url']); diff --git a/tests/StorageDriverTest.php b/tests/StorageDriverTest.php index 77160144..1472cd7e 100755 --- a/tests/StorageDriverTest.php +++ b/tests/StorageDriverTest.php @@ -120,9 +120,7 @@ public function testGetDocumentation() public function testGetDocumentationFileNotExists() { - $this->expectException(FileNotFoundException::class); - - $this->expectExceptionMessageMatches('/^Documentation file not found documentation.json$/'); + $this->assertExceptionThrew(FileNotFoundException::class, 'Documentation file not found documentation.json'); self::$storageDriverClass->getDocumentation(); } diff --git a/tests/TestCase.php b/tests/TestCase.php index 91706921..d3f91c81 100755 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -13,9 +13,10 @@ use RonasIT\AutoDoc\Tests\Support\Mock\TestController; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; use Symfony\Component\HttpFoundation\Response; - +use RonasIT\Support\Traits\TestingTrait; class TestCase extends BaseTest { + use TestingTrait; protected bool $globalExportMode = false; public function setUp(): void From c86b6f9402c15785ab294ffd5bc1e6d463da5948 Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Tue, 27 May 2025 14:43:06 +0300 Subject: [PATCH 15/19] style:add empty spaces --- tests/TestCase.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/TestCase.php b/tests/TestCase.php index d3f91c81..13242929 100755 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -14,9 +14,11 @@ use Symfony\Component\HttpFoundation\Request as SymfonyRequest; use Symfony\Component\HttpFoundation\Response; use RonasIT\Support\Traits\TestingTrait; + class TestCase extends BaseTest { use TestingTrait; + protected bool $globalExportMode = false; public function setUp(): void From a997c5d956b2d10680096a3e4329146ddbde343e Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Thu, 29 May 2025 13:43:09 +0300 Subject: [PATCH 16/19] style: add empty spaces --- src/Services/SwaggerService.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index a8c56d45..1a91587a 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -140,7 +140,7 @@ protected function generateEmptyData(?string $view = null, array $viewData = [], throw new EmptyContactEmailException(); } - if(empty($view) && !empty($this->config['info'])){ + if (empty($view) && !empty($this->config['info'])){ $view = $this->config['info']['description']; } @@ -602,8 +602,8 @@ protected function saveParameterType(&$data, $parameter, $parameterType) } protected function saveParameterDescription( - &$data, - $parameter, + array &$data, + string $parameter, array $rulesArray, array $attributes, array $annotations @@ -964,7 +964,7 @@ protected function prepareInfo(?string $view = null, array $viewData = [], array { $info = []; - $license = array_filter($license, fn($value) => !empty($value)); + $license = array_filter($license); if (!empty($license)) { $info['license'] = $license; @@ -974,9 +974,7 @@ protected function prepareInfo(?string $view = null, array $viewData = [], array $info['description'] = view($view, $viewData)->render(); } - $infoConfig = Arr::except($this->config['info'], ['description', 'license']); - - return array_merge($infoConfig, $info); + return array_merge(Arr::except($this->config['info'], ['description', 'license']), $info); } protected function getOpenAPIFileContent(string $filePath): array From 11c2c1b7bc9c08f711baf8f696987530fd7e0db3 Mon Sep 17 00:00:00 2001 From: DenTray Date: Mon, 2 Jun 2025 09:33:24 +0600 Subject: [PATCH 17/19] Apply suggestions from code review --- src/Services/SwaggerService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index 1a91587a..1dd0e981 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -832,7 +832,7 @@ public function getDocFileContent() $this->openAPIValidator->validate($documentation); } catch (Exception $exception) { - return $this->generateEmptyData($this->config['defaults']['error'], ['message' => $exception->getMessage()]); + return $this->generateEmptyData($this->config['defaults']['error'], ['message' => $exception->getMessage()]); } $additionalDocs = config('auto-doc.additional_paths', []); @@ -974,7 +974,7 @@ protected function prepareInfo(?string $view = null, array $viewData = [], array $info['description'] = view($view, $viewData)->render(); } - return array_merge(Arr::except($this->config['info'], ['description', 'license']), $info); + return array_merge($this->config['info'], $info); } protected function getOpenAPIFileContent(string $filePath): array From b06ff97b87ae66066d5329aef4d16314530fd16f Mon Sep 17 00:00:00 2001 From: Ruslan Guskov Date: Mon, 2 Jun 2025 12:34:55 +0300 Subject: [PATCH 18/19] fix:tests --- src/Services/SwaggerService.php | 4 ++-- .../tmp_data_request_with_empty_data_jwt.json | 4 ++++ .../tmp_data_request_with_empty_data_laravel.json | 4 ++++ .../tmp_data_request_with_empty_data_query.json | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index 1a91587a..b4541614 100755 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -973,8 +973,8 @@ protected function prepareInfo(?string $view = null, array $viewData = [], array if (!empty($view)) { $info['description'] = view($view, $viewData)->render(); } - - return array_merge(Arr::except($this->config['info'], ['description', 'license']), $info); + + return array_merge($this->config['info'], $info); } protected function getOpenAPIFileContent(string $filePath): array diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_jwt.json b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_jwt.json index 2c994d33..82907a7f 100644 --- a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_jwt.json +++ b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_jwt.json @@ -16,6 +16,10 @@ "termsOfService": "", "contact": { "email": "your@mail.com" + }, + "license": { + "name": "", + "url": "" } }, "securityDefinitions": { diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_laravel.json b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_laravel.json index 53b5b5a3..010bd96e 100644 --- a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_laravel.json +++ b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_laravel.json @@ -16,6 +16,10 @@ "termsOfService": "", "contact": { "email": "your@mail.com" + }, + "license": { + "name": "", + "url": "" } }, "securityDefinitions": { diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_query.json b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_query.json index 8b95d9c9..026c3087 100644 --- a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_query.json +++ b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_query.json @@ -16,6 +16,10 @@ "termsOfService": "", "contact": { "email": "your@mail.com" + }, + "license": { + "name": "", + "url": "" } }, "securityDefinitions": { From 822934d0bb93c336894a09e08eedded62dd7260d Mon Sep 17 00:00:00 2001 From: DenTray Date: Tue, 3 Jun 2025 09:33:57 +0600 Subject: [PATCH 19/19] Update src/Services/SwaggerService.php --- src/Services/SwaggerService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php index b81eeff3..b6074986 100644 --- a/src/Services/SwaggerService.php +++ b/src/Services/SwaggerService.php @@ -140,7 +140,7 @@ protected function generateEmptyData(?string $view = null, array $viewData = [], throw new EmptyContactEmailException(); } - if (empty($view) && !empty($this->config['info'])){ + if (empty($view) && !empty($this->config['info'])) { $view = $this->config['info']['description']; }