Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/run-tests-with-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Execute unit tests via PHPUnit with coverage
run: vendor/bin/phpunit --coverage-clover build/logs/clover.xml
run: vendor/bin/phpunit --debug --coverage-clover build/logs/clover.xml
- name: Export coverage report
if: ${{ matrix.php-version == '8.4' }}
uses: actions/upload-artifact@v4
Expand All @@ -50,4 +50,4 @@ jobs:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
composer global require php-coveralls/php-coveralls
php-coveralls --coverage_clover=build/logs/clover.xml -v --json_path=coveralls-upload.json
php-coveralls --verbose --coverage_clover=build/logs/clover.xml -v --json_path=coveralls-upload.json
5 changes: 5 additions & 0 deletions lang/en/validation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
'unhandled_error_message' => 'Documentation file is empty or have bad format',
];
15 changes: 14 additions & 1 deletion resources/views/error.blade.php
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
{{ $message }}
# ❗️ **ERROR** ❗️

## 🚨🚨 {{ $type }} 🚨🚨

---

### **Details:**

{{ $message }}

### **Error place:**

{{ $error_place }}
---
2 changes: 2 additions & 0 deletions src/AutoDocServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public function boot()
{
$this->mergeConfigFrom(__DIR__ . '/../config/auto-doc.php', 'auto-doc');

$this->loadTranslationsFrom(__DIR__ . '/../lang', 'auto-doc');

$this->publishes([
__DIR__ . '/../config/auto-doc.php' => config_path('auto-doc.php'),
], 'config');
Expand Down
76 changes: 55 additions & 21 deletions src/Services/SwaggerService.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use RonasIT\AutoDoc\Traits\GetDependenciesTrait;
use RonasIT\AutoDoc\Validators\SwaggerSpecValidator;
use Symfony\Component\HttpFoundation\Response;
use Throwable;
use Exception;

/**
Expand Down Expand Up @@ -73,6 +74,10 @@ public function __construct(Container $container)
$this->setDriver();

if (config('app.env') === 'testing') {
// client must enter at least `contact.email` to generate a default `info` block
// otherwise an exception will be called
$this->checkEmail();

$this->container = $container;

$this->security = $this->config['security'];
Expand All @@ -84,6 +89,23 @@ public function __construct(Container $container)

$this->driver->saveProcessTmpData($this->data);
}
} else {
try {
$this->checkEmail();
} catch (EmptyContactEmailException $exception) {
$this->data = $this->generateEmptyData(
$this->config['defaults']['error'],
[
'message' => $exception->getMessage(),
'type' => $exception::class,
'error_place' => $this->getErrorPlace($exception),
],
);

$this->driver->saveProcessTmpData($this->data);

$this->driver->saveData();
}
}
}

Expand Down Expand Up @@ -134,12 +156,6 @@ protected function setDriver()

protected function generateEmptyData(?string $view = null, array $viewData = [], array $license = []): array
{
// 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')) {
throw new EmptyContactEmailException();
}

if (empty($view) && !empty($this->config['info'])) {
$view = $this->config['info']['description'];
}
Expand All @@ -165,6 +181,13 @@ protected function generateEmptyData(?string $view = null, array $viewData = [],
return $data;
}

protected function checkEmail(): void
{
if (!empty($this->config['info']) && !Arr::get($this->config, 'info.contact.email')) {
throw new EmptyContactEmailException();
}
}

protected function generateSecurityDefinition(): ?array
{
if (empty($this->security)) {
Expand Down Expand Up @@ -796,18 +819,6 @@ protected function getActionName($uri): string
return Str::camel($action);
}

/**
* @deprecated method is not in use
* @codeCoverageIgnore
*/
protected function saveTempData()
{
$exportFile = Arr::get($this->config, 'files.temporary');
$data = json_encode($this->data);

file_put_contents($exportFile, $data);
}

public function saveProductionData()
{
if (ParallelTesting::token()) {
Expand All @@ -831,8 +842,19 @@ public function getDocFileContent()
$documentation = $this->driver->getDocumentation();

$this->openAPIValidator->validate($documentation);
} catch (Exception $exception) {
return $this->generateEmptyData($this->config['defaults']['error'], ['message' => $exception->getMessage()]);
} catch (Throwable $exception) {
$message = ($exception instanceof Exception)
? $exception->getMessage()
: __('validation.unhandled_error_message');

return $this->generateEmptyData(
$this->config['defaults']['error'],
[
'message' => $message,
'type' => $exception::class,
'error_place' => $this->getErrorPlace($exception),
]
);
}

$additionalDocs = config('auto-doc.additional_paths', []);
Expand All @@ -852,6 +874,18 @@ public function getDocFileContent()
return $documentation;
}

protected function getErrorPlace(Throwable $exception): string
{
$errorPlaceInTrace = Arr::first($exception->getTrace());

$errorPlaceInTrace = implode(', ', Arr::map(
$errorPlaceInTrace,
fn ($value, $key) => $key . '=' . (is_array($value) ? json_encode($value) : $value),
));

return $errorPlaceInTrace;
}

protected function camelCaseToUnderScore($input): string
{
preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
Expand Down Expand Up @@ -973,7 +1007,7 @@ protected function prepareInfo(?string $view = null, array $viewData = [], array
if (!empty($view)) {
$info['description'] = view($view, $viewData)->render();
}

return array_merge($this->config['info'], $info);
}

Expand Down
21 changes: 20 additions & 1 deletion tests/AutoDocControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

use Illuminate\Http\Response;
use phpmock\phpunit\PHPMock;
use RonasIT\AutoDoc\Tests\Support\Traits\TraceMockTrait;

class AutoDocControllerTest extends TestCase
{
use PHPMock;
use PHPMock, TraceMockTrait;

protected static array $documentation;
protected static string $localDriverFilePath;
Expand Down Expand Up @@ -40,6 +41,24 @@ public function testGetJSONDocumentation()
$response->assertJson(self::$documentation);
}

public function testGetJSONWithoutEmailDocumentation()
{
config([
'auto-doc.info.contact.email' => null,
'app.env' => 'development',
]);

$response = $this->json('get', '/auto-doc/documentation');

$response->assertStatus(Response::HTTP_OK);

$content = $response->json();

$this->mockGetTrace($content['info']['description']);

$this->assertEqualsJsonFixture('documentation_without_email', $content);
}

public function testGetJSONDocumentationWithAdditionalPaths()
{
config([
Expand Down
12 changes: 10 additions & 2 deletions tests/SwaggerServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
use RonasIT\AutoDoc\Tests\Support\Traits\SwaggerServiceMockTrait;
use RonasIT\AutoDoc\Tests\Support\Traits\SwaggerServiceTestingTrait;
use stdClass;
use RonasIT\AutoDoc\Tests\Support\Traits\TraceMockTrait;

class SwaggerServiceTest extends TestCase
{
use SwaggerServiceMockTrait, SwaggerServiceTestingTrait;
use SwaggerServiceMockTrait, SwaggerServiceTestingTrait, TraceMockTrait;

public function testConstructorInvalidConfigVersion()
{
Expand Down Expand Up @@ -223,6 +224,10 @@ public static function getConstructorInvalidTmpData(): array
'tmpDoc' => 'documentation/invalid_format__response__invalid_items',
'fixture' => 'invalid_format_response_invalid_items.html',
],
[
'tmpDoc' => 'documentation/tmp_data_incorrect_documentation_structure_request',
'fixture' => 'invalid_format_incorrect_documentation_structure_request.html',
],
];
}

Expand All @@ -234,6 +239,8 @@ public function testGetDocFileContentInvalidTmpData(
$this->mockDriverGetDocumentation($this->getJsonFixture($tmpDoc));

$content = app(SwaggerService::class)->getDocFileContent();
dd($content['info']['description']);
$this->mockGetTrace($content['info']['description']);

$this->assertEqualsFixture($fixture, $content['info']['description']);
}
Expand All @@ -243,8 +250,9 @@ public function testEmptyContactEmail()
config(['auto-doc.info.contact.email' => null]);

$this->expectException(EmptyContactEmailException::class);
$this->expectExceptionMessage('Please fill the `info.contact.email` field in the app-doc.php config file.');

app(SwaggerService::class);
app(SwaggerService::class)->getDocFileContent();
}

public static function getAddEmptyData(): array
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function assertEqualsJsonFixture(string $fixtureName, $data, bool $export
public function assertEqualsFixture(string $fixtureName, $data, bool $exportMode = false): void
{
if ($exportMode || $this->globalExportMode) {
$this->exportContent($fixtureName, $data);
$this->exportContent($data, $fixtureName);
}

$this->assertEquals($this->getFixture($fixtureName), $data);
Expand Down
90 changes: 0 additions & 90 deletions tests/fixtures/AutoDocControllerTest/documentation__non_json.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"openapi": "3.1.0",
"servers": [
{
"url": "http:\/\/localhost"
}
],
"paths": [],
"components": {
"schemas": []
},
"info": {
"description": "# ❗️ **ERROR** ❗️\n\n## 🚨🚨 RonasIT\\AutoDoc\\Exceptions\\EmptyContactEmailException 🚨🚨\n\n---\n\n### **Details:**\n\nPlease fill the `info.contact.email` field in the app-doc.php config file.\n\n### **Error place:**\n\nfile=\/app\/src\/Services\/SwaggerService.php, line=999, function=checkEmail, class=RonasIT\\AutoDoc\\Services\\SwaggerService, type=-&gt;, args=[]\n---",
"version": "0.0.0",
"title": "Name of Your Application",
"termsOfService": "",
"contact": {
"email": null
},
"license": {
"name": "",
"url": ""
}
}
}
Loading
Loading