Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 4 additions & 3 deletions src/Symfony/Action/DocumentationAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function __construct(
private readonly array $documentationFormats = [OpenApiNormalizer::JSON_FORMAT => ['application/vnd.openapi+json'], OpenApiNormalizer::FORMAT => ['application/json']],
private readonly bool $swaggerUiEnabled = true,
private readonly bool $docsEnabled = true,
private readonly bool $reDocEnabled = true,
) {
$this->negotiator = $negotiator ?? new Negotiator();
}
Expand Down Expand Up @@ -90,8 +91,8 @@ public function __invoke(?Request $request = null)
*/
private function getOpenApiDocumentation(array $context, string $format, Request $request): OpenApi|Response
{
if ('html' === $format && !$this->swaggerUiEnabled) {
throw new NotFoundHttpException('Swagger UI is disabled.');
if ('html' === $format && !$this->swaggerUiEnabled && !$this->reDocEnabled) {
throw new NotFoundHttpException('Swagger UI and ReDoc are disabled.');
}

if ($this->provider && $this->processor) {
Expand All @@ -104,7 +105,7 @@ class: OpenApi::class,
outputFormats: $this->documentationFormats
);

if ('html' === $format && $this->swaggerUiEnabled) {
if ('html' === $format && ($this->swaggerUiEnabled || $this->reDocEnabled)) {
$operation = $operation->withProcessor('api_platform.swagger_ui.processor')->withWrite(true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ private function registerSwaggerConfiguration(ContainerBuilder $container, array
$loader->load('openapi/yaml.php');
}

if ($config['enable_swagger_ui']) {
if ($config['enable_swagger_ui'] || $config['enable_re_doc']) {
$loader->load('swagger_ui.php');

if ($config['use_symfony_listeners']) {
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Bundle/Resources/config/symfony/controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@
'%api_platform.docs_formats%',
'%api_platform.enable_swagger_ui%',
'%api_platform.enable_docs%',
'%api_platform.enable_re_doc%',
]);
};
1 change: 1 addition & 0 deletions src/Symfony/Bundle/Resources/config/symfony/events.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
'%api_platform.docs_formats%',
'%api_platform.enable_swagger_ui%',
'%api_platform.enable_docs%',
'%api_platform.enable_re_doc%',
]);

$services->set('api_platform.action.placeholder', 'ApiPlatform\Symfony\Action\PlaceholderAction')
Expand Down
63 changes: 61 additions & 2 deletions src/Symfony/Tests/Action/DocumentationActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ class DocumentationActionTest extends TestCase
{
use ProphecyTrait;

public function testHtmlFormatWhenSwaggerUiDisabledThrows404(): void
public function testHtmlFormatWhenSwaggerUiAndReDocDisabledThrows404(): void
{
$this->expectException(NotFoundHttpException::class);
$this->expectExceptionMessage('Swagger UI is disabled.');
$this->expectExceptionMessage('Swagger UI and ReDoc are disabled.');

$request = new Request();
$request->attributes->set('_format', 'html');
Expand All @@ -55,11 +55,70 @@ public function testHtmlFormatWhenSwaggerUiDisabledThrows404(): void
'html' => ['text/html'],
],
swaggerUiEnabled: false,
reDocEnabled: false,
);

$documentation($request);
}

public function testHtmlFormatWhenReDocEnabledAndSwaggerUiDisabled(): void
{
$request = new Request();
$request->attributes->set('_format', 'html');

$openApiFactory = $this->createMock(OpenApiFactoryInterface::class);
$resourceNameCollectionFactory = $this->createMock(ResourceNameCollectionFactoryInterface::class);
$provider = $this->createMock(ProviderInterface::class);
$provider->expects($this->once())->method('provide')->willReturn(new OpenApi(new Info('title', '1.0.0'), [], new Paths()));
$processor = $this->createMock(ProcessorInterface::class);
$processor->expects($this->once())->method('process')->willReturnArgument(0);

$documentation = new DocumentationAction(
$resourceNameCollectionFactory,
openApiFactory: $openApiFactory,
provider: $provider,
processor: $processor,
documentationFormats: [
'json' => ['application/json'],
'html' => ['text/html'],
],
swaggerUiEnabled: false,
reDocEnabled: true,
);

$result = $documentation($request);
$this->assertInstanceOf(OpenApi::class, $result);
}

public function testHtmlFormatWhenSwaggerUiEnabledAndReDocDisabled(): void
{
$request = new Request();
$request->attributes->set('_format', 'html');

$openApiFactory = $this->createMock(OpenApiFactoryInterface::class);
$resourceNameCollectionFactory = $this->createMock(ResourceNameCollectionFactoryInterface::class);
$provider = $this->createMock(ProviderInterface::class);
$provider->expects($this->once())->method('provide')->willReturn(new OpenApi(new Info('title', '1.0.0'), [], new Paths()));
$processor = $this->createMock(ProcessorInterface::class);
$processor->expects($this->once())->method('process')->willReturnArgument(0);

$documentation = new DocumentationAction(
$resourceNameCollectionFactory,
openApiFactory: $openApiFactory,
provider: $provider,
processor: $processor,
documentationFormats: [
'json' => ['application/json'],
'html' => ['text/html'],
],
swaggerUiEnabled: true,
reDocEnabled: false,
);

$result = $documentation($request);
$this->assertInstanceOf(OpenApi::class, $result);
}

public function testJsonFormatWhenSwaggerUiDisabledIsAccessible(): void
{
$request = new Request();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ public function testSwaggerUiDisabledConfiguration(): void
$config = self::DEFAULT_CONFIG;
$config['api_platform']['enable_swagger'] = true;
$config['api_platform']['enable_swagger_ui'] = false;
$config['api_platform']['enable_re_doc'] = false;
$config['api_platform']['use_symfony_listeners'] = true;

(new ApiPlatformExtension())->load($config, $this->container);
Expand Down Expand Up @@ -300,6 +301,26 @@ public function testSwaggerUiEnabledConfiguration(): void
$this->assertContainerHas($services);
}

public function testReDocEnabledWithSwaggerUiDisabledConfiguration(): void
{
$config = self::DEFAULT_CONFIG;
$config['api_platform']['enable_swagger'] = true;
$config['api_platform']['enable_swagger_ui'] = false;
$config['api_platform']['enable_re_doc'] = true;
$config['api_platform']['use_symfony_listeners'] = true;

(new ApiPlatformExtension())->load($config, $this->container);

$services = [
'api_platform.swagger_ui.processor',
'api_platform.swagger_ui.context',
'api_platform.swagger_ui.provider',
'api_platform.swagger_ui.documentation.provider',
];

$this->assertContainerHas($services);
}

public function testEventListenersConfiguration(): void
{
$config = self::DEFAULT_CONFIG;
Expand Down
52 changes: 47 additions & 5 deletions tests/Functional/DocumentationActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@
class DocumentationActionAppKernel extends \AppKernel
{
public static bool $swaggerUiEnabled = true;
public static bool $reDocEnabled = true;

public function getCacheDir(): string
{
$suffix = self::$swaggerUiEnabled ? 'ui_enabled' : 'ui_disabled';
$suffix = (self::$swaggerUiEnabled ? 'ui_' : 'no_ui_').(self::$reDocEnabled ? 'redoc' : 'no_redoc');

return parent::getCacheDir().'/'.$suffix;
}

public function getLogDir(): string
{
$suffix = self::$swaggerUiEnabled ? 'ui_enabled' : 'ui_disabled';
$suffix = (self::$swaggerUiEnabled ? 'ui_' : 'no_ui_').(self::$reDocEnabled ? 'redoc' : 'no_redoc');

return parent::getLogDir().'/'.$suffix;
}
Expand All @@ -45,6 +46,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
$loader->load(static function (ContainerBuilder $container) {
$container->loadFromExtension('api_platform', [
'enable_swagger_ui' => DocumentationActionAppKernel::$swaggerUiEnabled,
'enable_re_doc' => DocumentationActionAppKernel::$reDocEnabled,
]);
});
}
Expand All @@ -59,57 +61,97 @@ protected static function getKernelClass(): string
return DocumentationActionAppKernel::class;
}

public function testHtmlDocumentationIsNotAccessibleWhenSwaggerUiIsDisabled(): void
public function testHtmlDocumentationIsNotAccessibleWhenSwaggerUiAndReDocAreDisabled(): void
{
DocumentationActionAppKernel::$swaggerUiEnabled = false;
DocumentationActionAppKernel::$reDocEnabled = false;

$client = self::createClient();

$container = static::getContainer();
$this->assertFalse($container->getParameter('api_platform.enable_swagger_ui'));
$this->assertFalse($container->getParameter('api_platform.enable_re_doc'));

$client->request('GET', '/docs', ['headers' => ['Accept' => 'text/html']]);
$this->assertResponseStatusCodeSame(404);
$this->assertStringContainsString('Swagger UI is disabled.', $client->getResponse()->getContent(false));
$this->assertStringContainsString('Swagger UI and ReDoc are disabled.', $client->getResponse()->getContent(false));
}

public function testJsonDocumentationIsAccessibleWhenSwaggerUiIsDisabled(): void
{
DocumentationActionAppKernel::$swaggerUiEnabled = false;
DocumentationActionAppKernel::$reDocEnabled = false;

$client = self::createClient();

$container = static::getContainer();
$this->assertFalse($container->getParameter('api_platform.enable_swagger_ui'));
$this->assertFalse($container->getParameter('api_platform.enable_re_doc'));

$client->request('GET', '/docs.jsonopenapi', ['headers' => ['Accept' => 'application/vnd.openapi+json']]);
$this->assertResponseIsSuccessful();
$this->assertJsonContains(['openapi' => '3.1.0']);
$this->assertJsonContains(['info' => ['title' => 'My Dummy API']]);
}

public function testHtmlDocumentationIsAccessibleWhenReDocEnabledAndSwaggerUiDisabled(): void
{
DocumentationActionAppKernel::$swaggerUiEnabled = false;
DocumentationActionAppKernel::$reDocEnabled = true;

$client = self::createClient();

$container = static::getContainer();
$this->assertFalse($container->getParameter('api_platform.enable_swagger_ui'));
$this->assertTrue($container->getParameter('api_platform.enable_re_doc'));

$client->request('GET', '/docs', ['headers' => ['Accept' => 'text/html']]);
$this->assertResponseIsSuccessful();
$this->assertStringNotContainsString('Swagger UI and ReDoc are disabled.', $client->getResponse()->getContent(false));
}

public function testHtmlDocumentationIsAccessibleWhenSwaggerUiEnabledAndReDocDisabled(): void
{
DocumentationActionAppKernel::$swaggerUiEnabled = true;
DocumentationActionAppKernel::$reDocEnabled = false;

$client = self::createClient();

$container = static::getContainer();
$this->assertTrue($container->getParameter('api_platform.enable_swagger_ui'));
$this->assertFalse($container->getParameter('api_platform.enable_re_doc'));

$client->request('GET', '/docs', ['headers' => ['Accept' => 'text/html']]);
$this->assertResponseIsSuccessful();
$this->assertStringNotContainsString('Swagger UI and ReDoc are disabled.', $client->getResponse()->getContent(false));
}

public function testHtmlDocumentationIsAccessibleWhenSwaggerUiIsEnabled(): void
{
DocumentationActionAppKernel::$swaggerUiEnabled = true;
DocumentationActionAppKernel::$reDocEnabled = true;

$client = self::createClient();

$container = static::getContainer();
$this->assertTrue($container->getParameter('api_platform.enable_swagger_ui'));
$this->assertTrue($container->getParameter('api_platform.enable_re_doc'));

$client->request('GET', '/docs', ['headers' => ['Accept' => 'text/html']]);
$this->assertResponseIsSuccessful();
$this->assertStringNotContainsString('Swagger UI is disabled.', $client->getResponse()->getContent(false));
$this->assertStringNotContainsString('Swagger UI and ReDoc are disabled.', $client->getResponse()->getContent(false));
}

public function testJsonDocumentationIsAccessibleWhenSwaggerUiIsEnabled(): void
{
DocumentationActionAppKernel::$swaggerUiEnabled = true;
DocumentationActionAppKernel::$reDocEnabled = true;

$client = self::createClient();

$container = static::getContainer();
$this->assertTrue($container->getParameter('api_platform.enable_swagger_ui'));
$this->assertTrue($container->getParameter('api_platform.enable_re_doc'));

$client->request('GET', '/docs.jsonopenapi', ['headers' => ['Accept' => 'application/vnd.openapi+json']]);
$this->assertResponseIsSuccessful();
Expand Down
Loading