Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
dee3246
refactor: display throwable errors too
RGO230 Jul 2, 2025
115f599
Merge branch '163-modify-500-code-error-response-page' of https://git…
RGO230 Jul 2, 2025
1c7dfcf
refactor: set empty array for not exception errors
RGO230 Jul 3, 2025
fe96b4b
refactor: add empty email exception message to view
RGO230 Jul 9, 2025
241a8f7
fix: remove useless
RGO230 Jul 9, 2025
6624b40
refactor: add defaul unhandled error message
RGO230 Sep 1, 2025
79d523c
refactor: use try catch
RGO230 Sep 11, 2025
66d348a
refactor: use try catch in correct place
RGO230 Sep 12, 2025
c48e7f2
fix: tests
RGO230 Sep 17, 2025
86a3613
refactor: remove useless
RGO230 Sep 17, 2025
2d6f294
style:fix
RGO230 Sep 24, 2025
2baa6e4
refactor: remove generateDataWithExceptionHandling
RGO230 Sep 28, 2025
b8c8e88
style:fix
RGO230 Sep 29, 2025
c779d33
refactor: mock getTraceMethod
RGO230 Oct 6, 2025
b5f1058
fix: make correct trace format
RGO230 Oct 6, 2025
e91f3c7
refactor: make TraceMockTrait
RGO230 Oct 6, 2025
70c3fe8
Merge branch 'master' into 163-modify-500-code-error-response-page
RGO230 Oct 6, 2025
500b9df
style:fix
RGO230 Oct 6, 2025
9cc86e5
style:fix
RGO230 Oct 6, 2025
9bc0e27
style:fix
RGO230 Oct 6, 2025
9435c06
Merge branch '163-modify-500-code-error-response-page' of https://git…
RGO230 Oct 6, 2025
0d5d70e
fix: correct find trace info in response content
RGO230 Oct 7, 2025
99e0fc5
refactor: make tests for github ci env
RGO230 Oct 7, 2025
9868465
fix:tests
RGO230 Oct 7, 2025
a48313b
fix:tests
RGO230 Oct 8, 2025
66d89d1
chore: add todo
RGO230 Oct 8, 2025
b36f48e
style: fix
RGO230 Oct 8, 2025
3a76139
fix: remove last changes
RGO230 Oct 8, 2025
8c95347
style: fix
RGO230 Oct 8, 2025
88a7aee
style:fix
RGO230 Oct 8, 2025
247de39
fix: remove useless
RGO230 Oct 9, 2025
b3fc2f7
refactor: add throwable in documentation driver
RGO230 Oct 14, 2025
5f0de86
tests:fix
RGO230 Oct 14, 2025
63a7bae
fix: tests
RGO230 Oct 15, 2025
33f9321
fix: tests
RGO230 Oct 15, 2025
c334ebf
fix: remove useless
RGO230 Oct 15, 2025
4a22c5d
fix: remove useless
RGO230 Oct 15, 2025
48f6b6a
Merge branch '163-modify-500-code-error-response-page' of https://git…
RGO230 Oct 15, 2025
bbb9954
Update src/Services/SwaggerService.php
DenTray Oct 16, 2025
2ffa2e0
Update src/AutoDocServiceProvider.php
DenTray Oct 16, 2025
a41dd8e
Apply suggestion from @DenTray
DenTray Oct 16, 2025
deb135f
refactor: separate invalid prod data test
RGO230 Oct 19, 2025
9aa1c07
refactor: use swagger service mock, remove useless
RGO230 Oct 26, 2025
ab733aa
fix: tests
RGO230 Oct 26, 2025
2618e5c
fix:tests
RGO230 Oct 26, 2025
186e3ab
style:fix
RGO230 Oct 26, 2025
5e8c8a1
fix: remove useless
RGO230 Oct 27, 2025
e134ca9
Apply suggestion from @Copilot
AZabolotnikov Oct 29, 2025
09aba3d
style:fix
RGO230 Nov 2, 2025
c83958a
fix:remove useless
RGO230 Nov 2, 2025
3331f1c
style:fix
RGO230 Nov 4, 2025
5eef605
fix:tests
RGO230 Nov 4, 2025
f70a93b
Update tests/SwaggerServiceTest.php
DenTray Nov 6, 2025
17c2b2a
Update tests/SwaggerServiceTest.php
DenTray Nov 6, 2025
a080402
Update tests/SwaggerServiceTest.php
DenTray Nov 6, 2025
229e545
Update tests/SwaggerServiceTest.php
DenTray Nov 6, 2025
4f0254c
Update tests/SwaggerServiceTest.php
DenTray Nov 6, 2025
a0ba34f
Update tests/SwaggerServiceTest.php
DenTray Nov 6, 2025
208ce11
Update tests/SwaggerServiceTest.php
DenTray Nov 6, 2025
5c8cfeb
Update tests/SwaggerServiceTest.php
DenTray Nov 6, 2025
c07712a
tests: make correct php 8.4 tests
RGO230 Nov 6, 2025
b6ab02c
Merge branch '163-modify-500-code-error-response-page' of https://git…
RGO230 Nov 6, 2025
30f0f23
fix:tests
RGO230 Nov 6, 2025
8a1c80b
refactor: remove useless
RGO230 Nov 6, 2025
b0030f3
refactor: replace getFixturePath to getFixture
RGO230 Nov 11, 2025
07ac086
style: remove useless
RGO230 Nov 11, 2025
5d00c6d
style: fix
RGO230 Nov 11, 2025
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
2 changes: 1 addition & 1 deletion .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: php -d zend.exception_ignore_args=0 -d xdebug.collect_params=4 vendor/bin/phpunit --coverage-clover build/logs/clover.xml
- name: Export coverage report
if: ${{ matrix.php-version == '8.4' }}
uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"orchestra/testbench": ">=9.3",
"php-coveralls/php-coveralls": "^2.7",
"php-mock/php-mock-phpunit": ">=2.10",
"ronasit/laravel-helpers": "^3.4"
"ronasit/laravel-helpers": "^3.5"
},
"autoload": {
"psr-4": {
Expand Down
18 changes: 9 additions & 9 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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 }}
---
11 changes: 11 additions & 0 deletions src/Drivers/LocalDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use RonasIT\AutoDoc\Exceptions\FileNotFoundException;
use RonasIT\AutoDoc\Exceptions\MissedProductionFilePathException;
use RonasIT\AutoDoc\Exceptions\EmptyDocFileException;
use RonasIT\AutoDoc\Exceptions\NonJSONDocFileException;
use Symfony\Component\Filesystem\Path;

class LocalDriver extends BaseDriver
{
Expand Down Expand Up @@ -35,6 +38,14 @@ public function getDocumentation(): array

$fileContent = file_get_contents($this->prodFilePath);

if (empty($fileContent)) {
throw new EmptyDocFileException(Path::makeRelative($this->prodFilePath, base_path()));
}

if (!json_validate($fileContent)) {
throw new NonJSONDocFileException(Path::makeRelative($this->prodFilePath, base_path()));
}

return json_decode($fileContent, true);
}
}
5 changes: 5 additions & 0 deletions src/Drivers/RemoteDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use RonasIT\AutoDoc\Exceptions\FileNotFoundException;
use RonasIT\AutoDoc\Exceptions\MissedRemoteDocumentationUrlException;
use RonasIT\AutoDoc\Exceptions\NonJSONDocFileException;

class RemoteDriver extends BaseDriver
{
Expand Down Expand Up @@ -39,6 +40,10 @@ public function getDocumentation(): array
throw new FileNotFoundException();
}

if (!json_validate($content)) {
throw new NonJSONDocFileException('Remote documentation');
}

return json_decode($content, true);
}

Expand Down
10 changes: 10 additions & 0 deletions src/Drivers/StorageDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Facades\Storage;
use RonasIT\AutoDoc\Exceptions\MissedProductionFilePathException;
use RonasIT\AutoDoc\Exceptions\EmptyDocFileException;
use RonasIT\AutoDoc\Exceptions\NonJSONDocFileException;

class StorageDriver extends BaseDriver
{
Expand Down Expand Up @@ -39,6 +41,14 @@ public function getDocumentation(): array

$fileContent = $this->disk->get($this->prodFilePath);

if (empty($fileContent)) {
throw new EmptyDocFileException($this->prodFilePath);
}

if (!json_validate($fileContent)) {
throw new NonJSONDocFileException($this->prodFilePath);
}

return json_decode($fileContent, true);
}
}
13 changes: 13 additions & 0 deletions src/Exceptions/NonJSONDocFileException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace RonasIT\AutoDoc\Exceptions;

use Exception;

class NonJSONDocFileException extends Exception
{
public function __construct(string $filename)
{
parent::__construct("Doc file '{$filename}' is not a json doc file.");
}
}
53 changes: 31 additions & 22 deletions src/Services/SwaggerService.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
use RonasIT\AutoDoc\Traits\GetDependenciesTrait;
use RonasIT\AutoDoc\Validators\SwaggerSpecValidator;
use Symfony\Component\HttpFoundation\Response;
use Exception;
use Throwable;

/**
* @property SwaggerDriverContract $driver
Expand Down Expand Up @@ -73,6 +73,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 Down Expand Up @@ -134,12 +138,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 +163,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 +801,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 +824,12 @@ 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) {
return $this->generateEmptyData($this->config['defaults']['error'], [
'message' => $exception->getMessage(),
'type' => $exception::class,
'error_place' => $this->getErrorPlace($exception),
]);
}

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

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

$formattedTraceEntry = Arr::map(
array: $firstTraceEntry,
callback: fn ($value, $key) => $key . '=' . (is_array($value) ? json_encode($value) : $value),
);

return implode(', ', $formattedTraceEntry);
}

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 +982,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
2 changes: 1 addition & 1 deletion tests/AutoDocControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function testGetJSONDocumentationIsEmpty()
$mock->expects($this->once());

config([
'auto-doc.additional_paths' => ['tests/fixtures/AutoDocControllerTest/documentation__non_json.txt'],
'auto-doc.additional_paths' => ['tests/fixtures/AutoDocControllerTest/empty_additional_documentation.json'],
]);

$response = $this->json('get', '/auto-doc/documentation');
Expand Down
22 changes: 21 additions & 1 deletion tests/LocalDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use RonasIT\AutoDoc\Drivers\LocalDriver;
use RonasIT\AutoDoc\Exceptions\FileNotFoundException;
use RonasIT\AutoDoc\Exceptions\MissedProductionFilePathException;
use RonasIT\AutoDoc\Exceptions\EmptyDocFileException;
use RonasIT\AutoDoc\Exceptions\NonJSONDocFileException;

class LocalDriverTest extends TestCase
{
Expand Down Expand Up @@ -37,7 +39,7 @@ public function testSaveProcessTmpData()

public function testSaveProcessTmpDataCheckTokenBasedPath()
{
$this->mockParallelTestingToken();
$this->mockParallelTestingToken('workerID');

$processTempFilePath = __DIR__ . '/../storage/temp_documentation_workerID.json';

Expand Down Expand Up @@ -124,6 +126,24 @@ public function testGetDocumentation()
$this->assertEqualsJsonFixture('tmp_data', $documentation);
}

public function testGetEmptyDocumentation(): void
{
file_put_contents(self::$productionFilePath, '');

$this->assertExceptionThrew(EmptyDocFileException::class, "Doc file 'storage/documentation.json' is empty.");

self::$localDriverClass->getDocumentation();
}

public function testGetInvalidJsonDocumentation(): void
{
file_put_contents(self::$productionFilePath, $this->getFixture('invalid_prod_json_data.json'));

$this->assertExceptionThrew(NonJSONDocFileException::class, "Doc file 'storage/documentation.json' is not a json doc file.");

self::$localDriverClass->getDocumentation();
}

public function testGetDocumentationFileNotExists()
{
$this->assertExceptionThrew(FileNotFoundException::class, 'Documentation file not found not_exists_file');
Expand Down
22 changes: 22 additions & 0 deletions tests/RemoteDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use RonasIT\AutoDoc\Drivers\RemoteDriver;
use RonasIT\AutoDoc\Exceptions\MissedRemoteDocumentationUrlException;
use RonasIT\AutoDoc\Exceptions\FileNotFoundException;
use RonasIT\AutoDoc\Exceptions\NonJSONDocFileException;

class RemoteDriverTest extends TestCase
{
Expand Down Expand Up @@ -146,6 +147,27 @@ public function testGetDocumentation()
$this->assertEquals(self::$tmpData, $documentation);
}

public function testGetInvalidJsonDocumentation(): void
{
$this->assertExceptionThrew(NonJSONDocFileException::class, "Doc file 'Remote documentation' is not a json doc file.");

config(['auto-doc.drivers.remote.key' => 'mocked_key']);
config(['auto-doc.drivers.remote.url' => 'mocked_url']);

$mock = $this->mockClass(RemoteDriver::class, [
$this->functionCall(
name: 'makeHttpRequest',
arguments: [
'get',
'mocked_url/documentations/mocked_key',
],
result: [$this->getFixture('invalid_prod_json_data.json'), 200],
),
]);

$mock->getDocumentation();
}

public function testGetDocumentationNoFile()
{
$this->assertExceptionThrew(FileNotFoundException::class, 'Documentation file not found ');
Expand Down
Loading