From 2af8d8eacd661e0601b2d6f4dbc1766bf75e702a Mon Sep 17 00:00:00 2001 From: shalvah Date: Tue, 6 Jul 2021 11:45:32 +0100 Subject: [PATCH 1/6] Improve spacing in UI --- resources/css/theme-default.style.css | 2 +- .../views/themes/default/endpoint.blade.php | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/resources/css/theme-default.style.css b/resources/css/theme-default.style.css index 5e21dd0f..75970f11 100644 --- a/resources/css/theme-default.style.css +++ b/resources/css/theme-default.style.css @@ -858,7 +858,7 @@ html { .content pre { background-color: #292929; color: #fff; - padding: 2em 28px; + padding: 1.5em 28px; margin: 0; width: 50%; float: right; diff --git a/resources/views/themes/default/endpoint.blade.php b/resources/views/themes/default/endpoint.blade.php index e08b4000..7b413dc2 100644 --- a/resources/views/themes/default/endpoint.blade.php +++ b/resources/views/themes/default/endpoint.blade.php @@ -32,24 +32,20 @@ Show headers -
-            @foreach($response->headers as $header => $value)
+            
@foreach($response->headers as $header => $value)
 {{ $header }}: {{ is_array($value) ? implode('; ', $value) : $value }}
-@endforeach 
-            
+@endforeach
@endif
-                
 @if(is_string($response->content) && Str::startsWith($response->content, "<>"))
-[Binary data] - {{ htmlentities(str_replace("<>", "", $response->content)) }}
+[Binary data] - {{ htmlentities(str_replace("<>", "", $response->content)) }}
 @elseif($response->status == 204)
-[Empty response]
+[Empty response]
 @else
 @php($parsed = json_decode($response->content))
 {{-- If response is a JSON string, prettify it. Otherwise, just print it --}}
-{!! htmlentities($parsed != null ? json_encode($parsed, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) : $response->content) !!}
-@endif 
-        
+{!! htmlentities($parsed != null ? json_encode($parsed, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) : $response->content) !!} +@endif @endforeach @endif From 579f672b57ad0417a5563aee1621b84c3b4ff1f2 Mon Sep 17 00:00:00 2001 From: shalvah Date: Tue, 6 Jul 2021 12:16:05 +0100 Subject: [PATCH 2/6] Turn off autocomplete in Try It Out; make sure it works for array body --- camel/Output/OutputEndpointData.php | 6 ++++++ resources/js/tryitout.js | 11 +++++++---- resources/views/components/field-details.blade.php | 2 ++ resources/views/themes/default/endpoint.blade.php | 2 ++ src/Commands/GenerateDocumentation.php | 2 +- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/camel/Output/OutputEndpointData.php b/camel/Output/OutputEndpointData.php index e0f85acb..13de1a45 100644 --- a/camel/Output/OutputEndpointData.php +++ b/camel/Output/OutputEndpointData.php @@ -150,6 +150,12 @@ public function hasFiles(): bool return count($this->fileParameters) > 0; } + public function isArrayBody(): bool + { + return count($this->nestedBodyParameters) === 1 + && array_keys($this->nestedBodyParameters)[0] === "[]"; + } + public function isGet(): bool { return in_array('GET', $this->httpMethods); diff --git a/resources/js/tryitout.js b/resources/js/tryitout.js index 824fc9ce..e10fd035 100644 --- a/resources/js/tryitout.js +++ b/resources/js/tryitout.js @@ -142,12 +142,15 @@ async function executeTryOut(endpointId, form) { let body; let setter; - if (form.dataset.hasfiles === "0") { - body = {}; - setter = (name, value) => _.set(body, name, value); - } else { + if (form.dataset.hasfiles === "1") { body = new FormData(); setter = (name, value) => body.append(name, value); + } else if (form.dataset.isarraybody === "1") { + body = []; + setter = (name, value) => _.set(body, name, value); + } else { + body = {}; + setter = (name, value) => _.set(body, name, value); } const bodyParameters = form.querySelectorAll('input[data-component=body]'); bodyParameters.forEach(el => { diff --git a/resources/views/components/field-details.blade.php b/resources/views/components/field-details.blade.php index 029565f3..3bd6d8fb 100644 --- a/resources/views/components/field-details.blade.php +++ b/resources/views/components/field-details.blade.php @@ -10,6 +10,8 @@ $fullName .= '.0'; $baseType = substr($baseType, 0, -2); } + // When the body is an array, the item names will be ".0.thing" + $fullName = ltrim($fullName, '.'); switch($baseType) { case 'number': case 'integer': diff --git a/resources/views/themes/default/endpoint.blade.php b/resources/views/themes/default/endpoint.blade.php index 7b413dc2..a228b125 100644 --- a/resources/views/themes/default/endpoint.blade.php +++ b/resources/views/themes/default/endpoint.blade.php @@ -63,7 +63,9 @@ data-path="{{ $endpoint->uri }}" data-authed="{{ $endpoint->metadata->authenticated ? 1 : 0 }}" data-hasfiles="{{ $endpoint->hasFiles() ? 1 : 0 }}" + data-isarraybody="{{ $endpoint->isArrayBody() ? 1 : 0 }}" data-headers='@json($endpoint->headers)' + autocomplete="off" onsubmit="event.preventDefault(); executeTryOut('{{ $endpoint->endpointId() }}', this);">

Request    diff --git a/src/Commands/GenerateDocumentation.php b/src/Commands/GenerateDocumentation.php index 284c2d5b..f0c39804 100644 --- a/src/Commands/GenerateDocumentation.php +++ b/src/Commands/GenerateDocumentation.php @@ -84,7 +84,7 @@ public function bootstrap(): void throw new \Exception("Can't use --force and --no-extraction together."); } - // Reset this map useful for tests) + // Reset this map (useful for tests) Camel::$groupFileNames = []; } From 6999b13c8dcc6347e85739796aee4083ca86c9c3 Mon Sep 17 00:00:00 2001 From: shalvah Date: Tue, 6 Jul 2021 12:41:59 +0100 Subject: [PATCH 3/6] Moar tests --- tests/GenerateDocumentationTest.php | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/GenerateDocumentationTest.php b/tests/GenerateDocumentationTest.php index 7a8e829b..87051627 100644 --- a/tests/GenerateDocumentationTest.php +++ b/tests/GenerateDocumentationTest.php @@ -485,4 +485,37 @@ public function respects_endpoints_and_group_sort_order() $this->assertEquals("Another endpoint.", $expectedEndpoints->getNode(1)->textContent); $this->assertEquals("Some endpoint.", $expectedEndpoints->getNode(2)->textContent); } + + /** @test */ + public function will_auto_set_content_type_to_multipart_if_file_params_are_present() + { + /** + * @bodyParam param string required + */ + RouteFacade::post('no-file', fn() => null); + /** + * @bodyParam a_file file required + */ + RouteFacade::post('top-level-file', fn() => null); + /** + * @bodyParam data object + * @bodyParam data.thing string + * @bodyParam data.a_file file + */ + RouteFacade::post('nested-file', fn() => null); + config(['scribe.routes.0.match.prefixes' => ['*']]); + config(['scribe.openapi.enabled' => false]); + config(['scribe.postman.enabled' => false]); + + $this->artisan('scribe:generate'); + + $group = Yaml::parseFile('.scribe/endpoints/0.yaml'); + $this->assertEquals('no-file', $group['endpoints'][0]['uri']); + $this->assertEquals('application/json', $group['endpoints'][0]['headers']['Content-Type']); + $this->assertEquals('top-level-file', $group['endpoints'][1]['uri']); + $this->assertEquals('multipart/form-data', $group['endpoints'][1]['headers']['Content-Type']); + $this->assertEquals('nested-file', $group['endpoints'][2]['uri']); + $this->assertEquals('multipart/form-data', $group['endpoints'][2]['headers']['Content-Type']); + + } } From 40ef51409a53314a607c73fffbde2fe138421a00 Mon Sep 17 00:00:00 2001 From: shalvah Date: Tue, 6 Jul 2021 12:42:03 +0100 Subject: [PATCH 4/6] 3.5.1 --- CHANGELOG.md | 4 ++++ src/Tools/Globals.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d26ef2d..95948063 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Removals +## 3.5.1 (Tuesday, 6 July 2021) +### Fixed +- Try It Out: Turn off autocomplete; make sure it works for array body; improve UI spacing ([579f672b57ad0417a5563aee1621b84c3b4ff1f2](https://github.com/knuckleswtf/scribe/commit/579f672b57ad0417a5563aee1621b84c3b4ff1f2), [2af8d8eacd661e0601b2d6f4dbc1766bf75e702a](https://github.com/knuckleswtf/scribe/commit/2af8d8eacd661e0601b2d6f4dbc1766bf75e702a)) + ## 3.5.0 (Monday, 5 July 2021) ### Modified - Get URL parameter name from field bindings (https://github.com/knuckleswtf/scribe/commit/ce6be7ca68ed0e682258eca5bbeb2f7d84774714) diff --git a/src/Tools/Globals.php b/src/Tools/Globals.php index 579294c1..c2c46bc3 100644 --- a/src/Tools/Globals.php +++ b/src/Tools/Globals.php @@ -4,7 +4,7 @@ class Globals { - public const SCRIBE_VERSION = '3.5.0'; + public const SCRIBE_VERSION = '3.5.1'; public static bool $shouldBeVerbose = false; } From 4fad273447b548c13f899948b4a44e50f5d28590 Mon Sep 17 00:00:00 2001 From: shalvah Date: Tue, 6 Jul 2021 12:44:11 +0100 Subject: [PATCH 5/6] Refactor tests --- tests/GenerateDocumentationTest.php | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/tests/GenerateDocumentationTest.php b/tests/GenerateDocumentationTest.php index 87051627..4779252a 100644 --- a/tests/GenerateDocumentationTest.php +++ b/tests/GenerateDocumentationTest.php @@ -22,6 +22,9 @@ protected function setUp(): void parent::setUp(); config(['scribe.database_connections_to_transact' => []]); + // Skip these ones for faster tests + config(['scribe.openapi.enabled' => false]); + config(['scribe.postman.enabled' => false]); $factory = app(\Illuminate\Database\Eloquent\Factory::class); $factory->define(TestUser::class, function () { @@ -206,7 +209,6 @@ public function generated_postman_collection_file_is_correct() ], ]); config(['scribe.postman.enabled' => true]); - config(['scribe.openapi.enabled' => false]); $this->artisan('scribe:generate'); @@ -230,7 +232,6 @@ public function generated_openapi_spec_file_is_correct() // We want to have the same values for params each time config(['scribe.faker_seed' => 1234]); - config(['scribe.postman.enabled' => false]); config(['scribe.openapi.enabled' => true]); config(['scribe.openapi.overrides' => [ 'info.version' => '3.9.9', @@ -372,8 +373,6 @@ public function generates_correct_url_params_from_resource_routes_and_field_bind ]); }); config(['scribe.routes.0.match.prefixes' => ['*']]); - config(['scribe.openapi.enabled' => false]); - config(['scribe.postman.enabled' => false]); $this->artisan('scribe:generate'); @@ -387,8 +386,6 @@ public function generates_correct_url_params_from_resource_routes_and_field_bind public function will_not_extract_if_noExtraction_flag_is_set() { config(['scribe.routes.0.exclude' => ['*']]); - config(['scribe.openapi.enabled' => false]); - config(['scribe.postman.enabled' => false]); Utils::copyDirectory(__DIR__.'/Fixtures/.scribe', '.scribe'); $output = $this->artisan('scribe:generate', ['--no-extraction' => true]); @@ -412,8 +409,6 @@ public function merges_user_defined_endpoints() RouteFacade::get('/api/action1', [TestGroupController::class, 'action1']); RouteFacade::get('/api/action2', [TestGroupController::class, 'action2']); config(['scribe.routes.0.match.prefixes' => ['api/*']]); - config(['scribe.openapi.enabled' => false]); - config(['scribe.postman.enabled' => false]); if (!is_dir('.scribe/endpoints')) mkdir('.scribe/endpoints', 0777, true); copy(__DIR__ . '/Fixtures/custom.0.yaml', '.scribe/endpoints/custom.0.yaml'); @@ -443,8 +438,6 @@ public function respects_endpoints_and_group_sort_order() RouteFacade::get('/api/action1b', [TestGroupController::class, 'action1b']); RouteFacade::get('/api/action2', [TestGroupController::class, 'action2']); config(['scribe.routes.0.match.prefixes' => ['api/*']]); - config(['scribe.openapi.enabled' => false]); - config(['scribe.postman.enabled' => false]); $this->artisan('scribe:generate'); @@ -504,8 +497,6 @@ public function will_auto_set_content_type_to_multipart_if_file_params_are_prese */ RouteFacade::post('nested-file', fn() => null); config(['scribe.routes.0.match.prefixes' => ['*']]); - config(['scribe.openapi.enabled' => false]); - config(['scribe.postman.enabled' => false]); $this->artisan('scribe:generate'); From 3b579eb8170249b0908da0a6ac3d408b3087a36e Mon Sep 17 00:00:00 2001 From: shalvah Date: Fri, 9 Jul 2021 10:31:24 +0100 Subject: [PATCH 6/6] Update docblocks --- .travis.yml | 7 +++---- src/Extracting/RouteDocBlocker.php | 2 +- src/Extracting/Strategies/Headers/GetFromHeaderTag.php | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0eccdcba..fe71f85a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,12 +10,12 @@ env: matrix: fast_finish: true include: - - php: 7.4 - env: COMPOSER=composer.dingo.json - name: "With Dingo router" - php: 7.4 env: SETUP=lint name: "Lint code" + - php: 7.4 + env: COMPOSER=composer.dingo.json + name: "With Dingo router" - php: 7.4.7 - php: 7.4 env: SETUP=lowest @@ -31,7 +31,6 @@ before_install: install: - if [[ $SETUP = 'stable' ]]; then travis_retry composer update --prefer-dist --prefer-stable; fi - if [[ $SETUP = 'lowest' ]]; then travis_retry composer require laravel/framework:^$LOWEST; composer require laravel/lumen-framework:^$LOWEST; fi - - if [[ $SETUP = 'lint' ]]; then travis_retry composer update --prefer-dist --prefer-stable; composer lint; fi script: - if [[ $SETUP = 'lint' ]]; then exit 0; fi; composer test-parallel-ci; diff --git a/src/Extracting/RouteDocBlocker.php b/src/Extracting/RouteDocBlocker.php index 49ae48ad..27fd8699 100644 --- a/src/Extracting/RouteDocBlocker.php +++ b/src/Extracting/RouteDocBlocker.php @@ -23,7 +23,7 @@ class RouteDocBlocker * @throws \ReflectionException * @throws \Exception * - * @return array<"method"|"class", DocBlock> Method and class docblocks + * @return array{method: DocBlock, class: DocBlock} Method and class docblocks */ public static function getDocBlocksFromRoute(Route $route): array { diff --git a/src/Extracting/Strategies/Headers/GetFromHeaderTag.php b/src/Extracting/Strategies/Headers/GetFromHeaderTag.php index ec948b4d..342148b0 100644 --- a/src/Extracting/Strategies/Headers/GetFromHeaderTag.php +++ b/src/Extracting/Strategies/Headers/GetFromHeaderTag.php @@ -56,7 +56,7 @@ public function __invoke(ExtractedEndpointData $endpointData, array $routeRules) return $this->getHeadersFromDocBlock($methodDocBlock->getTags()); } - public function getHeadersFromDocBlock($tags) + public function getHeadersFromDocBlock($tags): array { $headers = collect($tags) ->filter(function ($tag) {