Skip to content

Commit

Permalink
re-add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DjordyKoert committed Jan 2, 2024
1 parent c07abe0 commit c86bd62
Show file tree
Hide file tree
Showing 6 changed files with 551 additions and 5 deletions.
25 changes: 20 additions & 5 deletions Tests/RouteDescriber/Fixtures/DTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,40 @@ class DTO implements SelfDescribingModelInterface
public const DESCRIPTION = 'some description';

public function __construct(
private int $id,
private string $name,
private ?string $nullableName,
public int $id,
public string $name,
public ?string $nullableName,
#[OA\Property(
example: self::EXAMPLE_NAME,
)]
private string $nameWithExample,
public string $nameWithExample,
#[OA\Property(
description: self::DESCRIPTION,
)]
private string $nameWithDescription,
public string $nameWithDescription,
) {
}

public static function describe(Schema $schema, Model $model): void
{
$schema->type = 'object';
$schema->required = self::getRequired();
$schema->properties = self::getProperties();
}

/**
* @return string[]
*/
public static function getRequired(): array
{
return [
'id',
'name',
'nameWithExample',
'nameWithDescription',
];
}

/**
* @return Property[]
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public static function describe(Schema $schema, Model $model): void
$schema->description = $model->getType()->getClassName();
$schema->type = self::TYPE;

$schema->required = [
'id',
];
$schema->properties = self::getProperties();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php

declare(strict_types=1);

namespace Nelmio\ApiDocBundle\Tests\RouteDescriber\SymfonyAnnotationDescriber;

use Nelmio\ApiDocBundle\Annotation\Operation;
use Nelmio\ApiDocBundle\RouteDescriber\InlineParameterDescriber\SymfonyMapQueryParameterDescriber;
use Nelmio\ApiDocBundle\Tests\Functional\WebTestCase;
use OpenApi\Annotations\OpenApi;
use PHPUnit\Framework\TestCase;
use ReflectionAttribute;
use ReflectionParameter;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
use const PHP_VERSION_ID;

class SymfonyMapQueryParameterDescriberTest extends WebTestCase
{
/**
* @var SymfonyMapQueryParameterDescriber
*/
private $symfonyMapQueryParameterDescriber;

/**
* @var ArgumentMetadataFactoryInterface
*/
private $argumentMetadataFactory;

protected function setUp(): void
{
if (PHP_VERSION_ID < 80100) {
self::markTestSkipped('Attributes require PHP 8');
}

if (!class_exists(MapQueryParameter::class)) {
self::markTestSkipped('Symfony 6.3 MapQueryParameter attribute not found');
}

$this->argumentMetadataFactory = self::getContainer()->get('argument_metadata_factory');

$this->symfonyMapQueryParameterDescriber = new SymfonyMapQueryParameterDescriber();
}

/**
* @dataProvider provideMapQueryParameterTestData
*/
public function testMapQueryParameter(callable $function): void
{
$argumentMetaData = $this->argumentMetadataFactory->createArgumentMetadata($function)[0];

$this->symfonyMapQueryParameterDescriber->describe(
new OpenApi([]),
$operation = new Operation([]),
$argumentMetaData
);

/** @var MapQueryParameter $mapQueryParameter */
$mapQueryParameter = $argumentMetaData->getAttributes(MapQueryParameter::class, ArgumentMetadata::IS_INSTANCEOF)[0];

$documentationParameter = $operation->parameters[0];
self::assertSame($mapQueryParameter->name ?? $argumentMetaData->getName(), $documentationParameter->name);
self::assertSame('query', $documentationParameter->in);
self::assertSame(!$argumentMetaData->hasDefaultValue() && !$argumentMetaData->isNullable(), $documentationParameter->required);

$schema = $documentationParameter->schema;
self::assertSame('integer', $schema->type);
if ($argumentMetaData->hasDefaultValue()) {
self::assertSame($argumentMetaData->getDefaultValue(), $schema->default);
}

if (FILTER_VALIDATE_REGEXP === $mapQueryParameter->filter) {
self::assertSame($mapQueryParameter->options['regexp'], $schema->pattern);
}
}

public static function provideMapQueryParameterTestData(): iterable
{
yield 'it documents query parameters' => [
function (
#[MapQueryParameter] int $parameter1,
) {
},
];

yield 'it documents query parameters with default values' => [
function (
#[MapQueryParameter] int $parameter1 = 123,
) {
},
];

yield 'it documents query parameters with nullable types' => [
function (
#[MapQueryParameter] ?int $parameter1,
) {
},
];

yield 'it uses MapQueryParameter name argument as name' => [
function (
#[MapQueryParameter('someOtherParameter1Name')] int $parameter1,
) {
},
];

yield 'it documents regex pattern' => [
function (
#[MapQueryParameter(filter: FILTER_VALIDATE_REGEXP, options: ['regexp' => '/^\d+$/'])] int $parameter1,
) {
},
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?php

declare(strict_types=1);

namespace Nelmio\ApiDocBundle\Tests\RouteDescriber\SymfonyAnnotationDescriber;

use Nelmio\ApiDocBundle\Annotation\Operation;
use Nelmio\ApiDocBundle\Model\ModelRegistry;
use Nelmio\ApiDocBundle\ModelDescriber\SelfDescribingModelDescriber;
use Nelmio\ApiDocBundle\RouteDescriber\InlineParameterDescriber\SymfonyMapQueryStringDescriber;
use Nelmio\ApiDocBundle\Tests\Functional\WebTestCase;
use Nelmio\ApiDocBundle\Tests\RouteDescriber\Fixtures\DTO;
use Nelmio\ApiDocBundle\Tests\RouteDescriber\Fixtures\SymfonyDescriberMapQueryStringClass;
use OpenApi\Annotations\OpenApi;
use PHPUnit\Framework\TestCase;
use ReflectionParameter;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpKernel\Attribute\MapQueryString;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
use const PHP_VERSION_ID;

class SymfonyMapQueryStringDescriberTest extends WebTestCase
{
/**
* @var OpenApi
*/
private $openApi;
/**
* @var SymfonyMapQueryStringDescriber
*/
private $symfonyMapQueryStringDescriber;

/**
* @var ArgumentMetadataFactoryInterface
*/
private $argumentMetadataFactory;

protected function setUp(): void
{
if (PHP_VERSION_ID < 80100) {
self::markTestSkipped('Attributes require PHP 8');
}

if (!class_exists(MapQueryString::class)) {
self::markTestSkipped('Symfony 6.3 MapQueryString attribute not found');
}

$this->argumentMetadataFactory = self::getContainer()->get('argument_metadata_factory');

$this->openApi = new OpenApi([]);

$this->symfonyMapQueryStringDescriber = new SymfonyMapQueryStringDescriber([new SelfDescribingModelDescriber()]);

$registry = new ModelRegistry([], $this->openApi, []);

$this->symfonyMapQueryStringDescriber->setModelRegistry($registry);
}

/**
* @dataProvider provideMapQueryStringTestData
*/
public function testMapQueryString(callable $function, bool $required): void
{
$argumentMetaData = $this->argumentMetadataFactory->createArgumentMetadata($function)[0];

$this->symfonyMapQueryStringDescriber->describe(
$this->openApi,
$operation = new Operation([]),
$argumentMetaData
);

// Test it registers the model
$modelSchema = $this->openApi->components->schemas[0];
$expectedModelProperties = SymfonyDescriberMapQueryStringClass::getProperties();

self::assertSame(SymfonyDescriberMapQueryStringClass::SCHEMA, $modelSchema->schema);
self::assertSame(SymfonyDescriberMapQueryStringClass::TITLE, $modelSchema->title);
self::assertSame(SymfonyDescriberMapQueryStringClass::TYPE, $modelSchema->type);
self::assertEquals($expectedModelProperties, $modelSchema->properties);

foreach ($expectedModelProperties as $key => $expectedModelProperty) {
$queryParameter = $operation->parameters[$key];

self::assertSame('query', $queryParameter->in);
self::assertSame($expectedModelProperty->property, $queryParameter->name);
self::assertSame($required, $queryParameter->required);
}
}

public static function provideMapQueryStringTestData(): iterable
{
yield 'it documents query string parameters' => [
function (
#[MapQueryString] SymfonyDescriberMapQueryStringClass $parameter1,
) {
},
true
];

yield 'it documents a nullable type as optional' => [
function (
#[MapQueryString] ?SymfonyDescriberMapQueryStringClass $parameter1,
) {
},
false
];

yield 'it documents a default value as optional' => [
function (
#[MapQueryString] ?SymfonyDescriberMapQueryStringClass $parameter1,
) {
},
false
];
}

public function testItDescribesProperties(): void
{
$function = function (
#[MapQueryString] DTO $DTO,
) {
};

$argumentMetaData = $this->argumentMetadataFactory->createArgumentMetadata($function)[0];

$this->symfonyMapQueryStringDescriber->describe(
$this->openApi,
$operation = new Operation([]),
$argumentMetaData
);

// Test it registers the model
$modelSchema = $this->openApi->components->schemas[0];

self::assertEquals('object', $modelSchema->type);
self::assertEquals(DTO::getRequired(), $modelSchema->required);
self::assertEquals(DTO::getProperties(), $modelSchema->properties);

self::assertSame('id', $operation->parameters[0]->name);
self::assertSame('int', $operation->parameters[0]->schema->type);

self::assertSame('name', $operation->parameters[1]->name);

self::assertSame('nullableName', $operation->parameters[2]->name);
self::assertSame('string', $operation->parameters[2]->schema->type);
self::assertSame(false, $operation->parameters[2]->required);
self::assertSame(true, $operation->parameters[2]->schema->nullable);

self::assertSame('nameWithExample', $operation->parameters[3]->name);
self::assertSame('string', $operation->parameters[3]->schema->type);
self::assertSame(true, $operation->parameters[3]->required);
self::assertSame(DTO::EXAMPLE_NAME, $operation->parameters[3]->schema->example);
self::assertSame(DTO::EXAMPLE_NAME, $operation->parameters[3]->example);

self::assertSame('nameWithDescription', $operation->parameters[4]->name);
self::assertSame('string', $operation->parameters[4]->schema->type);
self::assertSame(true, $operation->parameters[4]->required);
self::assertSame(DTO::DESCRIPTION, $operation->parameters[4]->schema->description);
self::assertSame(DTO::DESCRIPTION, $operation->parameters[4]->description);
}
}
Loading

0 comments on commit c86bd62

Please sign in to comment.