mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-03 08:09:25 +03:00
857 lines
32 KiB
PHP
857 lines
32 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the NelmioApiDocBundle package.
|
|
*
|
|
* (c) Nelmio
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Nelmio\ApiDocBundle\Tests\SwaggerPhp;
|
|
|
|
use Nelmio\ApiDocBundle\OpenApiPhp\Util;
|
|
use OpenApi\Annotations as OA;
|
|
use OpenApi\Context;
|
|
use OpenApi\Generator;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Class UtilTest.
|
|
*
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::getOperation
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::getOperationParameter
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::getChild
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::getCollectionItem
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::getIndexedCollectionItem
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::searchCollectionItem
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::searchIndexedCollectionItem
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::createCollectionItem
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::createChild
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::createContext
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::merge
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::mergeFromArray
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::mergeChild
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::mergeCollection
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::mergeTyped
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::mergeProperty
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::getNestingIndexes
|
|
* @covers \Nelmio\ApiDocBundle\OpenApiPhp\Util::getNesting
|
|
*/
|
|
class UtilTest extends TestCase
|
|
{
|
|
public $rootContext;
|
|
|
|
/** @var OA\OpenApi */
|
|
public $rootAnnotation;
|
|
|
|
public function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->rootContext = new Context(['isTestingRoot' => true]);
|
|
$this->rootAnnotation = new OA\OpenApi(['_context' => $this->rootContext]);
|
|
}
|
|
|
|
public function testCreateContextSetsParentContext()
|
|
{
|
|
$context = Util::createContext([], $this->rootContext);
|
|
|
|
$this->assertContextIsConnectedToRootContext($context);
|
|
}
|
|
|
|
public function testCreateContextWithProperties()
|
|
{
|
|
$context = Util::createContext(['testing' => 'trait']);
|
|
|
|
$this->assertTrue($context->is('testing'));
|
|
$this->assertSame('trait', $context->testing);
|
|
}
|
|
|
|
public function testCreateChild()
|
|
{
|
|
$info = Util::createChild($this->rootAnnotation, OA\Info::class);
|
|
|
|
$this->assertInstanceOf(OA\Info::class, $info);
|
|
}
|
|
|
|
public function testCreateChildHasContext()
|
|
{
|
|
$info = Util::createChild($this->rootAnnotation, OA\Info::class);
|
|
|
|
$this->assertInstanceOf(Context::class, $info->_context);
|
|
}
|
|
|
|
public function testCreateChildHasNestedContext()
|
|
{
|
|
$path = Util::createChild($this->rootAnnotation, OA\PathItem::class);
|
|
$this->assertIsNested($this->rootAnnotation, $path);
|
|
|
|
$parameter = Util::createChild($path, OA\Parameter::class);
|
|
$this->assertIsNested($path, $parameter);
|
|
|
|
$schema = Util::createChild($parameter, OA\Schema::class);
|
|
$this->assertIsNested($parameter, $schema);
|
|
|
|
$this->assertIsConnectedToRootContext($schema);
|
|
}
|
|
|
|
public function testCreateChildWithEmptyProperties()
|
|
{
|
|
$properties = [];
|
|
/** @var OA\Info $info */
|
|
$info = Util::createChild($this->rootAnnotation, OA\Info::class, $properties);
|
|
|
|
$properties = array_filter(get_object_vars($info), function ($key) {
|
|
return 0 !== strpos($key, '_');
|
|
}, ARRAY_FILTER_USE_KEY);
|
|
|
|
$this->assertEquals([Generator::UNDEFINED], array_unique(array_values($properties)));
|
|
|
|
$this->assertIsNested($this->rootAnnotation, $info);
|
|
$this->assertIsConnectedToRootContext($info);
|
|
}
|
|
|
|
public function testCreateChildWithProperties()
|
|
{
|
|
$properties = ['title' => 'testing', 'version' => '999', 'x' => new \stdClass()];
|
|
/** @var OA\Info $info */
|
|
$info = Util::createChild($this->rootAnnotation, OA\Info::class, $properties);
|
|
|
|
$this->assertSame($info->title, $properties['title']);
|
|
$this->assertSame($info->version, $properties['version']);
|
|
$this->assertSame($info->x, $properties['x']);
|
|
|
|
$this->assertIsNested($this->rootAnnotation, $info);
|
|
$this->assertIsConnectedToRootContext($info);
|
|
}
|
|
|
|
public function testCreateCollectionItemAddsCreatedItemToCollection()
|
|
{
|
|
$collection = 'paths';
|
|
$class = OA\PathItem::class;
|
|
|
|
$p1 = Util::createCollectionItem($this->rootAnnotation, $collection, $class);
|
|
$this->assertSame(0, $p1);
|
|
$this->assertCount(1, $this->rootAnnotation->{$collection});
|
|
$this->assertInstanceOf($class, $this->rootAnnotation->{$collection}[$p1]);
|
|
$this->assertIsNested($this->rootAnnotation, $this->rootAnnotation->{$collection}[$p1]);
|
|
$this->assertIsConnectedToRootContext($this->rootAnnotation->{$collection}[$p1]);
|
|
|
|
$p2 = Util::createCollectionItem($this->rootAnnotation, $collection, $class);
|
|
$this->assertSame(1, $p2);
|
|
$this->assertCount(2, $this->rootAnnotation->{$collection});
|
|
$this->assertInstanceOf($class, $this->rootAnnotation->{$collection}[$p2]);
|
|
$this->assertIsNested($this->rootAnnotation, $this->rootAnnotation->{$collection}[$p2]);
|
|
$this->assertIsConnectedToRootContext($this->rootAnnotation->{$collection}[$p2]);
|
|
|
|
$this->rootAnnotation->components = Util::createChild($this->rootAnnotation, OA\Components::class);
|
|
|
|
$collection = 'schemas';
|
|
$class = OA\Schema::class;
|
|
|
|
$d1 = Util::createCollectionItem($this->rootAnnotation->components, $collection, $class);
|
|
$this->assertSame(0, $d1);
|
|
$this->assertCount(1, $this->rootAnnotation->components->{$collection});
|
|
$this->assertInstanceOf($class, $this->rootAnnotation->components->{$collection}[$d1]);
|
|
$this->assertIsNested($this->rootAnnotation->components, $this->rootAnnotation->components->{$collection}[$d1]);
|
|
$this->assertIsConnectedToRootContext($this->rootAnnotation->components->{$collection}[$d1]);
|
|
}
|
|
|
|
public function testCreateCollectionItemDoesNotAddToUnknownProperty()
|
|
{
|
|
$collection = 'foobars';
|
|
$class = OA\Info::class;
|
|
|
|
$expectedRegex = "/Property \"{$collection}\" doesn't exist .*/";
|
|
set_error_handler(function ($_, $err) { echo $err; });
|
|
$this->expectOutputRegex($expectedRegex);
|
|
Util::createCollectionItem($this->rootAnnotation, $collection, $class);
|
|
$this->expectOutputRegex($expectedRegex);
|
|
$this->assertNull($this->rootAnnotation->{$collection});
|
|
restore_error_handler();
|
|
}
|
|
|
|
public function testSearchCollectionItem()
|
|
{
|
|
$item1 = new \stdClass();
|
|
$item1->prop1 = 'item 1 prop 1';
|
|
$item1->prop2 = 'item 1 prop 2';
|
|
$item1->prop3 = 'item 1 prop 3';
|
|
|
|
$item2 = new \stdClass();
|
|
$item2->prop1 = 'item 2 prop 1';
|
|
$item2->prop2 = 'item 2 prop 2';
|
|
$item2->prop3 = 'item 2 prop 3';
|
|
|
|
$collection = [
|
|
$item1,
|
|
$item2,
|
|
];
|
|
|
|
$this->assertSame(0, Util::searchCollectionItem($collection, get_object_vars($item1)));
|
|
$this->assertSame(1, Util::searchCollectionItem($collection, get_object_vars($item2)));
|
|
|
|
$this->assertNull(Util::searchCollectionItem(
|
|
$collection,
|
|
array_merge(get_object_vars($item2), ['prop3' => 'foobar'])
|
|
));
|
|
|
|
$search = ['baz' => 'foobar'];
|
|
$this->expectOutputString('Undefined property: stdClass::$baz');
|
|
|
|
try {
|
|
Util::searchCollectionItem($collection, array_merge(get_object_vars($item2), $search));
|
|
} catch (\Exception $e) {
|
|
echo $e->getMessage();
|
|
}
|
|
|
|
// no exception on empty collection
|
|
$this->assertNull(Util::searchCollectionItem([], get_object_vars($item2)));
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideIndexedCollectionData
|
|
*/
|
|
public function testSearchIndexedCollectionItem($setup, $asserts)
|
|
{
|
|
foreach ($asserts as $collection => $items) {
|
|
foreach ($items as $assert) {
|
|
$setupCollection = empty($assert['components']) ?
|
|
($setup[$collection] ?? []) :
|
|
(Generator::UNDEFINED !== $setup['components']->{$collection} ? $setup['components']->{$collection} : []);
|
|
|
|
// get the indexing correct within haystack preparation
|
|
$properties = array_fill(0, \count($setupCollection), null);
|
|
|
|
// prepare the haystack array
|
|
foreach ($items as $assertItem) {
|
|
// e.g. $properties[1] = new OA\PathItem(['path' => 'path 1'])
|
|
$properties[$assertItem['index']] = new $assertItem['class']([
|
|
$assertItem['key'] => $assertItem['value'],
|
|
]);
|
|
}
|
|
|
|
$this->assertSame(
|
|
$assert['index'],
|
|
Util::searchIndexedCollectionItem($properties, $assert['key'], $assert['value']),
|
|
sprintf('Failed to get the correct index for %s', print_r($assert, true))
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideIndexedCollectionData
|
|
*/
|
|
public function testGetIndexedCollectionItem($setup, $asserts)
|
|
{
|
|
$parent = new $setup['class'](array_merge(
|
|
$this->getSetupPropertiesWithoutClass($setup),
|
|
['_context' => $this->rootContext]
|
|
));
|
|
|
|
foreach ($asserts as $collection => $items) {
|
|
foreach ($items as $assert) {
|
|
$itemParent = empty($assert['components']) ? $parent : $parent->components;
|
|
|
|
$child = Util::getIndexedCollectionItem(
|
|
$itemParent,
|
|
$assert['class'],
|
|
$assert['value']
|
|
);
|
|
|
|
$this->assertInstanceOf($assert['class'], $child);
|
|
$this->assertSame($child->{$assert['key']}, $assert['value']);
|
|
$this->assertSame(
|
|
$itemParent->{$collection}[$assert['index']],
|
|
$child
|
|
);
|
|
|
|
$setupHaystack = empty($assert['components']) ?
|
|
$setup[$collection] ?? [] :
|
|
$setup['components']->{$collection} ?? [];
|
|
|
|
// the children created within provider are not connected
|
|
if (!\in_array($child, $setupHaystack, true)) {
|
|
$this->assertIsNested($itemParent, $child);
|
|
$this->assertIsConnectedToRootContext($child);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function provideIndexedCollectionData(): array
|
|
{
|
|
return [[
|
|
'setup' => [
|
|
'class' => OA\OpenApi::class,
|
|
'paths' => [
|
|
new OA\PathItem(['path' => 'path 0']),
|
|
],
|
|
'components' => new OA\Components([
|
|
'parameters' => [
|
|
new OA\Parameter(['parameter' => 'parameter 0']),
|
|
new OA\Parameter(['parameter' => 'parameter 1']),
|
|
],
|
|
]),
|
|
],
|
|
'assert' => [
|
|
// one fixed within setup and one dynamically created
|
|
'paths' => [
|
|
[
|
|
'index' => 0,
|
|
'class' => OA\PathItem::class,
|
|
'key' => 'path',
|
|
'value' => 'path 0',
|
|
],
|
|
[
|
|
'index' => 1,
|
|
'class' => OA\PathItem::class,
|
|
'key' => 'path',
|
|
'value' => 'path 1',
|
|
],
|
|
],
|
|
// search indexes out of order followed by dynamically created
|
|
'parameters' => [
|
|
[
|
|
'index' => 1,
|
|
'class' => OA\Parameter::class,
|
|
'key' => 'parameter',
|
|
'value' => 'parameter 1',
|
|
'components' => true,
|
|
],
|
|
[
|
|
'index' => 0,
|
|
'class' => OA\Parameter::class,
|
|
'key' => 'parameter',
|
|
'value' => 'parameter 0',
|
|
'components' => true,
|
|
],
|
|
[
|
|
'index' => 2,
|
|
'class' => OA\Parameter::class,
|
|
'key' => 'parameter',
|
|
'value' => 'parameter 2',
|
|
'components' => true,
|
|
],
|
|
],
|
|
// two dynamically created
|
|
'responses' => [
|
|
[
|
|
'index' => 0,
|
|
'class' => OA\Response::class,
|
|
'key' => 'response',
|
|
'value' => 'response 0',
|
|
'components' => true,
|
|
],
|
|
[
|
|
'index' => 1,
|
|
'class' => OA\Response::class,
|
|
'key' => 'response',
|
|
'value' => 'response 1',
|
|
'components' => true,
|
|
],
|
|
],
|
|
// for sake of completeness
|
|
'securitySchemes' => [
|
|
[
|
|
'index' => 0,
|
|
'class' => OA\SecurityScheme::class,
|
|
'key' => 'securityScheme',
|
|
'value' => 'securityScheme 0',
|
|
'components' => true,
|
|
],
|
|
],
|
|
],
|
|
]];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideChildData
|
|
*/
|
|
public function testGetChild($setup, $asserts)
|
|
{
|
|
$parent = new $setup['class'](array_merge(
|
|
$this->getSetupPropertiesWithoutClass($setup),
|
|
['_context' => $this->rootContext]
|
|
));
|
|
|
|
foreach ($asserts as $key => $assert) {
|
|
if (array_key_exists('exceptionMessage', $assert)) {
|
|
$this->expectExceptionMessage($assert['exceptionMessage']);
|
|
}
|
|
$child = Util::getChild($parent, $assert['class'], $assert['props']);
|
|
|
|
$this->assertInstanceOf($assert['class'], $child);
|
|
$this->assertSame($child, $parent->{$key});
|
|
|
|
if (\array_key_exists($key, $setup)) {
|
|
$this->assertSame($setup[$key], $parent->{$key});
|
|
}
|
|
|
|
$this->assertEquals($assert['props'], $this->getNonDefaultProperties($child));
|
|
}
|
|
}
|
|
|
|
public function provideChildData(): array
|
|
{
|
|
return [[
|
|
'setup' => [
|
|
'class' => OA\PathItem::class,
|
|
'get' => new OA\Get([]),
|
|
],
|
|
'assert' => [
|
|
// fixed within setup
|
|
'get' => [
|
|
'class' => OA\Get::class,
|
|
'props' => [],
|
|
],
|
|
// create new without props
|
|
'put' => [
|
|
'class' => OA\Put::class,
|
|
'props' => [],
|
|
],
|
|
// create new with multiple props
|
|
'delete' => [
|
|
'class' => OA\Delete::class,
|
|
'props' => [
|
|
'summary' => 'testing delete',
|
|
'deprecated' => true,
|
|
],
|
|
],
|
|
],
|
|
], [
|
|
'setup' => [
|
|
'class' => OA\Parameter::class,
|
|
],
|
|
'assert' => [
|
|
// create new with multiple props
|
|
'schema' => [
|
|
'class' => OA\Schema::class,
|
|
'props' => [
|
|
'ref' => '#/testing/schema',
|
|
'minProperties' => 0,
|
|
'enum' => [null, 'check', 999, false],
|
|
],
|
|
],
|
|
],
|
|
], [
|
|
'setup' => [
|
|
'class' => OA\Parameter::class,
|
|
],
|
|
'assert' => [
|
|
// externalDocs triggers invalid argument exception
|
|
'schema' => [
|
|
'class' => OA\Schema::class,
|
|
'props' => [
|
|
'externalDocs' => [],
|
|
],
|
|
'exceptionMessage' => 'Nesting Annotations is not supported.',
|
|
],
|
|
],
|
|
]];
|
|
}
|
|
|
|
public function testGetOperationParameterReturnsExisting()
|
|
{
|
|
$name = 'operation name';
|
|
$in = 'operation in';
|
|
|
|
$parameter = new OA\Parameter(['name' => $name, 'in' => $in]);
|
|
$operation = new OA\Get(['parameters' => [
|
|
new OA\Parameter([]),
|
|
new OA\Parameter(['name' => 'foo']),
|
|
new OA\Parameter(['in' => 'bar']),
|
|
new OA\Parameter(['name' => $name, 'in' => 'bar']),
|
|
new OA\Parameter(['name' => 'foo', 'in' => $in]),
|
|
$parameter,
|
|
]]);
|
|
|
|
$actual = Util::getOperationParameter($operation, $name, $in);
|
|
$this->assertSame($parameter, $actual);
|
|
}
|
|
|
|
public function testGetOperationParameterCreatesWithNameAndIn()
|
|
{
|
|
$name = 'operation name';
|
|
$in = 'operation in';
|
|
|
|
$operation = new OA\Get(['parameters' => [
|
|
new OA\Parameter([]),
|
|
new OA\Parameter(['name' => 'foo']),
|
|
new OA\Parameter(['in' => 'bar']),
|
|
new OA\Parameter(['name' => $name, 'in' => 'bar']),
|
|
new OA\Parameter(['name' => 'foo', 'in' => $in]),
|
|
]]);
|
|
|
|
$actual = Util::getOperationParameter($operation, $name, $in);
|
|
$this->assertInstanceOf(OA\Parameter::class, $actual);
|
|
$this->assertSame($name, $actual->name);
|
|
$this->assertSame($in, $actual->in);
|
|
}
|
|
|
|
public function testGetOperationReturnsExisting()
|
|
{
|
|
$get = new OA\Get([]);
|
|
$path = new OA\PathItem(['get' => $get]);
|
|
|
|
$this->assertSame($get, Util::getOperation($path, 'get'));
|
|
}
|
|
|
|
public function testGetOperationCreatesWithPath()
|
|
{
|
|
$pathStr = '/testing/get/path';
|
|
$path = new OA\PathItem(['path' => $pathStr]);
|
|
|
|
$get = Util::getOperation($path, 'get');
|
|
$this->assertInstanceOf(OA\Get::class, $get);
|
|
$this->assertSame($pathStr, $get->path);
|
|
}
|
|
|
|
public function testMergeWithEmptyArray()
|
|
{
|
|
$api = new OA\OpenApi([]);
|
|
$expected = json_encode($api);
|
|
|
|
Util::merge($api, [], false);
|
|
$actual = json_encode($api);
|
|
|
|
$this->assertSame($expected, $actual);
|
|
|
|
Util::merge($api, [], true);
|
|
$actual = json_encode($api);
|
|
|
|
$this->assertSame($expected, $actual);
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideMergeData
|
|
*/
|
|
public function testMerge($setup, $merge, $assert)
|
|
{
|
|
$api = new OA\OpenApi($setup);
|
|
|
|
Util::merge($api, $merge, false);
|
|
$this->assertTrue($api->validate());
|
|
$actual = json_decode(json_encode($api), true);
|
|
|
|
$this->assertEquals($assert, $actual);
|
|
}
|
|
|
|
public function provideMergeData(): array
|
|
{
|
|
$no = 'do not overwrite';
|
|
$yes = 'do overwrite';
|
|
|
|
$requiredInfo = ['title' => '', 'version' => ''];
|
|
|
|
$setupDefaults = [
|
|
'info' => new OA\Info($requiredInfo),
|
|
'paths' => [],
|
|
];
|
|
$assertDefaults = [
|
|
'info' => $requiredInfo,
|
|
'openapi' => '3.0.0',
|
|
'paths' => [],
|
|
];
|
|
|
|
return [[
|
|
// simple child merge
|
|
'setup' => [
|
|
'info' => new OA\Info(['version' => $no]),
|
|
'paths' => [],
|
|
],
|
|
'merge' => [
|
|
'info' => ['title' => $yes, 'version' => $yes],
|
|
],
|
|
'assert' => [
|
|
'info' => ['title' => $yes, 'version' => $no],
|
|
] + $assertDefaults,
|
|
], [
|
|
// indexed collection merge
|
|
'setup' => [
|
|
'components' => new OA\Components([
|
|
'schemas' => [
|
|
new OA\Schema(['schema' => $no, 'title' => $no]),
|
|
],
|
|
]),
|
|
] + $setupDefaults,
|
|
'merge' => [
|
|
'components' => [
|
|
'schemas' => [
|
|
$no => ['title' => $yes, 'description' => $yes],
|
|
],
|
|
],
|
|
],
|
|
'assert' => [
|
|
'components' => [
|
|
'schemas' => [
|
|
$no => ['title' => $no, 'description' => $yes],
|
|
],
|
|
],
|
|
] + $assertDefaults,
|
|
], [
|
|
// collection merge
|
|
'setup' => [
|
|
'tags' => [new OA\Tag(['name' => $no])],
|
|
] + $setupDefaults,
|
|
'merge' => [
|
|
'tags' => [
|
|
// this is actually appending right now, no clue if this is wanted,
|
|
// but the complete NelmioApiDocBundle test suite is not upset by this fact
|
|
['name' => $yes],
|
|
// this should not append since a tag with exactly the same properties
|
|
// is already present
|
|
['name' => $no],
|
|
// this does, but should not append since the name already exists, and the
|
|
// docs in Tag state that the tag names must be unique, but it is complicated
|
|
// and $api->validate() does not complain either
|
|
['name' => $no, 'description' => $yes],
|
|
],
|
|
],
|
|
'assert' => [
|
|
'tags' => [
|
|
['name' => $no],
|
|
['name' => $yes],
|
|
['name' => $no, 'description' => $yes],
|
|
],
|
|
] + $assertDefaults,
|
|
],
|
|
[
|
|
// heavy nested merge array
|
|
'setup' => $setupDefaults,
|
|
'merge' => $merge = [
|
|
'servers' => [
|
|
['url' => 'http'],
|
|
['url' => 'https'],
|
|
],
|
|
'paths' => [
|
|
'/path/to/resource' => [
|
|
'get' => [
|
|
'responses' => [
|
|
'200' => [
|
|
'$ref' => '#/components/responses/default',
|
|
],
|
|
],
|
|
'requestBody' => [
|
|
'description' => 'request foo',
|
|
'content' => [
|
|
'foo-request' => [
|
|
'schema' => [
|
|
'type' => 'object',
|
|
'required' => ['baz', 'bar'],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
'tags' => [
|
|
['name' => 'baz'],
|
|
['name' => 'foo'],
|
|
['name' => 'baz'],
|
|
['name' => 'foo'],
|
|
['name' => 'foo'],
|
|
],
|
|
'components' => [
|
|
'responses' => [
|
|
'default' => [
|
|
'description' => 'default response',
|
|
'headers' => [
|
|
'foo-header' => [
|
|
'schema' => [
|
|
'type' => 'array',
|
|
'items' => [
|
|
'type' => 'string',
|
|
'enum' => ['foo', 'bar', 'baz'],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
'assert' => array_merge(
|
|
$assertDefaults,
|
|
$merge,
|
|
['tags' => \array_slice($merge['tags'], 0, 2, true)]
|
|
),
|
|
], [
|
|
// heavy nested merge array object
|
|
'setup' => $setupDefaults,
|
|
'merge' => new \ArrayObject([
|
|
'servers' => [
|
|
['url' => 'http'],
|
|
['url' => 'https'],
|
|
],
|
|
'paths' => [
|
|
'/path/to/resource' => [
|
|
'get' => new \ArrayObject([
|
|
'responses' => [
|
|
'200' => [
|
|
'$ref' => '#/components/responses/default',
|
|
],
|
|
],
|
|
'requestBody' => new \ArrayObject([
|
|
'description' => 'request foo',
|
|
'content' => [
|
|
'foo-request' => [
|
|
'schema' => [
|
|
'required' => ['baz', 'bar'],
|
|
'type' => 'object',
|
|
],
|
|
],
|
|
],
|
|
]),
|
|
]),
|
|
],
|
|
],
|
|
'tags' => new \ArrayObject([
|
|
['name' => 'baz'],
|
|
['name' => 'foo'],
|
|
new \ArrayObject(['name' => 'baz']),
|
|
['name' => 'foo'],
|
|
['name' => 'foo'],
|
|
]),
|
|
'components' => new \ArrayObject([
|
|
'responses' => [
|
|
'default' => [
|
|
'description' => 'default response',
|
|
'headers' => new \ArrayObject([
|
|
'foo-header' => new \ArrayObject([
|
|
'schema' => new \ArrayObject([
|
|
'type' => 'array',
|
|
'items' => new \ArrayObject([
|
|
'type' => 'string',
|
|
'enum' => ['foo', 'bar', 'baz'],
|
|
]),
|
|
]),
|
|
]),
|
|
]),
|
|
],
|
|
],
|
|
]),
|
|
]),
|
|
'assert' => array_merge(
|
|
$assertDefaults,
|
|
$merge,
|
|
['tags' => \array_slice($merge['tags'], 0, 2, true)]
|
|
),
|
|
], [
|
|
// heavy nested merge swagger instance
|
|
'setup' => $setupDefaults,
|
|
'merge' => new OA\OpenApi([
|
|
'servers' => [
|
|
new OA\Server(['url' => 'http']),
|
|
new OA\Server(['url' => 'https']),
|
|
],
|
|
'paths' => [
|
|
new OA\PathItem([
|
|
'path' => '/path/to/resource',
|
|
'get' => new OA\Get([
|
|
'responses' => [
|
|
new OA\Response([
|
|
'response' => '200',
|
|
'ref' => '#/components/responses/default',
|
|
]),
|
|
],
|
|
'requestBody' => new OA\RequestBody([
|
|
'description' => 'request foo',
|
|
'content' => [
|
|
new OA\MediaType([
|
|
'mediaType' => 'foo-request',
|
|
'schema' => new OA\Schema([
|
|
'type' => 'object',
|
|
'required' => ['baz', 'bar'],
|
|
]),
|
|
]),
|
|
],
|
|
]),
|
|
]),
|
|
]),
|
|
],
|
|
'tags' => [
|
|
new OA\Tag(['name' => 'baz']),
|
|
new OA\Tag(['name' => 'foo']),
|
|
new OA\Tag(['name' => 'baz']),
|
|
new OA\Tag(['name' => 'foo']),
|
|
new OA\Tag(['name' => 'foo']),
|
|
],
|
|
'components' => new OA\Components([
|
|
'responses' => [
|
|
new OA\Response([
|
|
'response' => 'default',
|
|
'description' => 'default response',
|
|
'headers' => [
|
|
new OA\Header([
|
|
'header' => 'foo-header',
|
|
'schema' => new OA\Schema([
|
|
'type' => 'array',
|
|
'items' => new OA\Items([
|
|
'type' => 'string',
|
|
'enum' => ['foo', 'bar', 'baz'],
|
|
]),
|
|
]),
|
|
]),
|
|
],
|
|
]),
|
|
],
|
|
]),
|
|
]),
|
|
'assert' => array_merge(
|
|
$assertDefaults,
|
|
$merge,
|
|
['tags' => \array_slice($merge['tags'], 0, 2, true)]
|
|
),
|
|
], ];
|
|
}
|
|
|
|
public function assertIsNested(OA\AbstractAnnotation $parent, OA\AbstractAnnotation $child)
|
|
{
|
|
self::assertTrue($child->_context->is('nested'));
|
|
self::assertSame($parent, $child->_context->nested);
|
|
}
|
|
|
|
public function assertIsConnectedToRootContext(OA\AbstractAnnotation $annotation)
|
|
{
|
|
$this->assertContextIsConnectedToRootContext($annotation->_context);
|
|
}
|
|
|
|
public function assertContextIsConnectedToRootContext(Context $context)
|
|
{
|
|
// zircote/swagger-php < 4.2 support
|
|
$getRootContext = \Closure::bind(function (Context $context) use (&$getRootContext) {
|
|
if (null !== $context->_parent) {
|
|
return $getRootContext($context->_parent);
|
|
}
|
|
|
|
return $context;
|
|
}, null, Context::class);
|
|
|
|
$this->assertSame($this->rootContext, $getRootContext($context));
|
|
}
|
|
|
|
private function getSetupPropertiesWithoutClass(array $setup)
|
|
{
|
|
return array_filter($setup, function ($k) {return 'class' !== $k; }, ARRAY_FILTER_USE_KEY);
|
|
}
|
|
|
|
private function getNonDefaultProperties($object)
|
|
{
|
|
$objectVars = \get_object_vars($object);
|
|
$classVars = \get_class_vars(\get_class($object));
|
|
$props = [];
|
|
foreach ($objectVars as $key => $value) {
|
|
if ($value !== $classVars[$key] && 0 !== \strpos($key, '_')) {
|
|
$props[$key] = $value;
|
|
}
|
|
}
|
|
|
|
return $props;
|
|
}
|
|
}
|