Merge branch 'master' into small-refactor-route-docblocker

This commit is contained in:
Shalvah
2021-07-09 10:36:11 +01:00
committed by GitHub
11 changed files with 68 additions and 32 deletions

View File

@@ -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;

View File

@@ -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)

View File

@@ -150,6 +150,12 @@ class OutputEndpointData extends BaseDTO
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);

View File

@@ -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;

View File

@@ -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 => {

View File

@@ -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':

View File

@@ -32,24 +32,20 @@
<summary>
<small onclick="textContent = parentElement.parentElement.open ? 'Show headers' : 'Hide headers'">Show headers</small>
</summary>
<pre>
<code class="language-http">@foreach($response->headers as $header => $value)
<pre><code class="language-http">@foreach($response->headers as $header => $value)
{{ $header }}: {{ is_array($value) ? implode('; ', $value) : $value }}
@endforeach </code>
</pre>
@endforeach </code></pre>
</details> @endif
<pre>
<code class="language-json">
@if(is_string($response->content) && Str::startsWith($response->content, "<<binary>>"))
[Binary data] - {{ htmlentities(str_replace("<<binary>>", "", $response->content)) }}
<code>[Binary data] - {{ htmlentities(str_replace("<<binary>>", "", $response->content)) }}</code>
@elseif($response->status == 204)
[Empty response]
<code>[Empty response]</code>
@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 </code>
</pre>
<code class="language-json">{!! htmlentities($parsed != null ? json_encode($parsed, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) : $response->content) !!}</code>
@endif </pre>
@endforeach
@endif
</span>
@@ -67,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);">
<h3>
Request&nbsp;&nbsp;&nbsp;

View File

@@ -84,7 +84,7 @@ class GenerateDocumentation extends Command
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 = [];
}

View File

@@ -56,7 +56,7 @@ class GetFromHeaderTag extends Strategy
return $this->getHeadersFromDocBlock($methodDocBlock->getTags());
}
public function getHeadersFromDocBlock($tags)
public function getHeadersFromDocBlock($tags): array
{
$headers = collect($tags)
->filter(function ($tag) {

View File

@@ -4,7 +4,7 @@ namespace Knuckles\Scribe\Tools;
class Globals
{
public const SCRIBE_VERSION = '3.5.0';
public const SCRIBE_VERSION = '3.5.1';
public static bool $shouldBeVerbose = false;
}

View File

@@ -22,6 +22,9 @@ class GenerateDocumentationTest extends BaseLaravelTest
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 @@ class GenerateDocumentationTest extends BaseLaravelTest
],
]);
config(['scribe.postman.enabled' => true]);
config(['scribe.openapi.enabled' => false]);
$this->artisan('scribe:generate');
@@ -230,7 +232,6 @@ class GenerateDocumentationTest extends BaseLaravelTest
// 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 @@ class GenerateDocumentationTest extends BaseLaravelTest
]);
});
config(['scribe.routes.0.match.prefixes' => ['*']]);
config(['scribe.openapi.enabled' => false]);
config(['scribe.postman.enabled' => false]);
$this->artisan('scribe:generate');
@@ -387,8 +386,6 @@ class GenerateDocumentationTest extends BaseLaravelTest
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 @@ class GenerateDocumentationTest extends BaseLaravelTest
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 @@ class GenerateDocumentationTest extends BaseLaravelTest
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');
@@ -485,4 +478,35 @@ class GenerateDocumentationTest extends BaseLaravelTest
$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' => ['*']]);
$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']);
}
}