From 21ade42ffe5317f54de07f41369f1f9dc515f6f3 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Thu, 14 Jul 2016 18:34:40 +0200 Subject: [PATCH 1/3] fix: add CollectionNormalizerTest --- .../Serializer/CollectionNormalizerTest.php | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 tests/Hydra/Serializer/CollectionNormalizerTest.php diff --git a/tests/Hydra/Serializer/CollectionNormalizerTest.php b/tests/Hydra/Serializer/CollectionNormalizerTest.php new file mode 100644 index 00000000000..65aa0169be5 --- /dev/null +++ b/tests/Hydra/Serializer/CollectionNormalizerTest.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ApiPlatform\Core\Tests\Hydra\Serializer; + +use ApiPlatform\Core\Api\IriConverterInterface; +use ApiPlatform\Core\Api\ResourceClassResolverInterface; +use ApiPlatform\Core\DataProvider\PaginatorInterface; +use ApiPlatform\Core\Hydra\Serializer\CollectionNormalizer; +use ApiPlatform\Core\JsonLd\ContextBuilderInterface; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use Symfony\Component\Serializer\SerializerInterface; + +/** + * @author Amrouche Hamza + * @author Kévin Dunglas + */ +class CollectionNormalizerTest extends \PHPUnit_Framework_TestCase +{ + public function testSupportsNormalize() + { + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $iriConvert = $this->prophesize(IriConverterInterface::class); + $contextBuilder = $this->prophesize(ContextBuilderInterface::class); + $contextBuilder->getResourceContextUri("Foo")->willReturn('/contexts/Foo'); + $iriConvert->getIriFromResourceClass("Foo")->willReturn('/foos'); + + $normalizer = new CollectionNormalizer($contextBuilder->reveal(), $resourceClassResolverProphecy->reveal(), $iriConvert->reveal()); + + $this->assertTrue($normalizer->supportsNormalization([], CollectionNormalizer::FORMAT)); + $this->assertTrue($normalizer->supportsNormalization(new \ArrayObject(), CollectionNormalizer::FORMAT)); + $this->assertFalse($normalizer->supportsNormalization([], 'xml')); + $this->assertFalse($normalizer->supportsNormalization(new \ArrayObject(), 'xml')); + } + + public function testNormalizeApiSubLevel() + { + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->getResourceClass(["foo" => "bar"], null, true)->willReturn('Foo')->shouldBeCalled(); + + $serializer = $this->prophesize(SerializerInterface::class); + $serializer->willImplement(NormalizerInterface::class); + $serializer->normalize('bar', null, ["jsonld_has_context" => true, "jsonld_sub_level" => true, "resource_class" => "Foo"])->willReturn(22); + $iriConvert = $this->prophesize(IriConverterInterface::class); + $contextBuilder = $this->prophesize(ContextBuilderInterface::class); + $contextBuilder->getResourceContextUri("Foo")->willReturn('/contexts/Foo'); + $iriConvert->getIriFromResourceClass("Foo")->willReturn('/foo/1'); + + $normalizer = new CollectionNormalizer($contextBuilder->reveal(), $resourceClassResolverProphecy->reveal(), $iriConvert->reveal()); + + $normalizer->setSerializer($serializer->reveal()); + + $this->assertEquals(['@context' => '/contexts/Foo', '@id' => '/foo/1', '@type' => 'hydra:Collection', 'hydra:member' => [0 => '22'], 'hydra:totalItems' => 1], $normalizer->normalize(['foo' => 'bar'], null)); + } + + public function testNormalizePaginator() + { + $paginatorProphecy = $this->prophesize(PaginatorInterface::class); + $paginatorProphecy->getCurrentPage()->willReturn(3); + $paginatorProphecy->getLastPage()->willReturn(7); + $paginatorProphecy->getItemsPerPage()->willReturn(12); + $paginatorProphecy->getTotalItems()->willReturn(1312); + $paginatorProphecy->rewind()->shouldBeCalled(); + $paginatorProphecy->valid()->willReturn(true, false)->shouldBeCalled(); + $paginatorProphecy->current()->willReturn('foo')->shouldBeCalled(); + $paginatorProphecy->next()->willReturn()->shouldBeCalled(); + $paginator = $paginatorProphecy->reveal(); + $serializer = $this->prophesize(SerializerInterface::class); + $serializer->willImplement(NormalizerInterface::class); + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->getResourceClass($paginator, null, true)->willReturn('Foo')->shouldBeCalled(); + + $serializer->normalize('foo', null, ["jsonld_has_context" => true, "jsonld_sub_level" => true, "resource_class" => "Foo"])->willReturn(['name' => 'Kévin', 'friend' => 'Smail']); + $iriConvert = $this->prophesize(IriConverterInterface::class); + $contextBuilder = $this->prophesize(ContextBuilderInterface::class); + $contextBuilder->getResourceContextUri("Foo")->willReturn('/contexts/Foo'); + $iriConvert->getIriFromResourceClass("Foo")->willReturn('/foo/1'); + + $normalizer = new CollectionNormalizer($contextBuilder->reveal(), $resourceClassResolverProphecy->reveal(), $iriConvert->reveal()); + + $normalizer->setSerializer($serializer->reveal()); + + $this->assertEquals(['@context' => '/contexts/Foo', '@id' => '/foo/1', '@type' => 'hydra:Collection', 'hydra:member' => [0 => ['name' => 'Kévin', 'friend' => 'Smail']], 'hydra:totalItems' => 1312.], $normalizer->normalize($paginator)); + } +} From cffda0070623cadf3731ddf3dc787ce43b03bba2 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Thu, 14 Jul 2016 18:43:35 +0200 Subject: [PATCH 2/3] fix: add itemNormalizerTest --- .../Serializer/CollectionNormalizerTest.php | 29 ++-- tests/Hydra/Serializer/ItemNormalizerTest.php | 130 ++++++++++++++++++ 2 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 tests/Hydra/Serializer/ItemNormalizerTest.php diff --git a/tests/Hydra/Serializer/CollectionNormalizerTest.php b/tests/Hydra/Serializer/CollectionNormalizerTest.php index 65aa0169be5..fafbea672bc 100644 --- a/tests/Hydra/Serializer/CollectionNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionNormalizerTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\DataProvider\PaginatorInterface; use ApiPlatform\Core\Hydra\Serializer\CollectionNormalizer; use ApiPlatform\Core\JsonLd\ContextBuilderInterface; +use ApiPlatform\Core\Serializer\AbstractItemNormalizer; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\SerializerInterface; @@ -30,8 +31,8 @@ public function testSupportsNormalize() $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $iriConvert = $this->prophesize(IriConverterInterface::class); $contextBuilder = $this->prophesize(ContextBuilderInterface::class); - $contextBuilder->getResourceContextUri("Foo")->willReturn('/contexts/Foo'); - $iriConvert->getIriFromResourceClass("Foo")->willReturn('/foos'); + $contextBuilder->getResourceContextUri('Foo')->willReturn('/contexts/Foo'); + $iriConvert->getIriFromResourceClass('Foo')->willReturn('/foos'); $normalizer = new CollectionNormalizer($contextBuilder->reveal(), $resourceClassResolverProphecy->reveal(), $iriConvert->reveal()); @@ -44,20 +45,18 @@ public function testSupportsNormalize() public function testNormalizeApiSubLevel() { $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(["foo" => "bar"], null, true)->willReturn('Foo')->shouldBeCalled(); + $resourceClassResolverProphecy->getResourceClass(['foo' => 'bar'], null, true)->willReturn('Foo')->shouldBeCalled(); - $serializer = $this->prophesize(SerializerInterface::class); - $serializer->willImplement(NormalizerInterface::class); - $serializer->normalize('bar', null, ["jsonld_has_context" => true, "jsonld_sub_level" => true, "resource_class" => "Foo"])->willReturn(22); $iriConvert = $this->prophesize(IriConverterInterface::class); $contextBuilder = $this->prophesize(ContextBuilderInterface::class); - $contextBuilder->getResourceContextUri("Foo")->willReturn('/contexts/Foo'); - $iriConvert->getIriFromResourceClass("Foo")->willReturn('/foo/1'); + $contextBuilder->getResourceContextUri('Foo')->willReturn('/contexts/Foo'); + $iriConvert->getIriFromResourceClass('Foo')->willReturn('/foo/1'); + $itemNormalizer = $this->prophesize(AbstractItemNormalizer::class); + $itemNormalizer->normalize('bar', null, ['jsonld_has_context' => true, 'api_sub_level' => true, 'resource_class' => 'Foo'])->willReturn(22); $normalizer = new CollectionNormalizer($contextBuilder->reveal(), $resourceClassResolverProphecy->reveal(), $iriConvert->reveal()); - $normalizer->setSerializer($serializer->reveal()); - + $normalizer->setNormalizer($itemNormalizer->reveal()); $this->assertEquals(['@context' => '/contexts/Foo', '@id' => '/foo/1', '@type' => 'hydra:Collection', 'hydra:member' => [0 => '22'], 'hydra:totalItems' => 1], $normalizer->normalize(['foo' => 'bar'], null)); } @@ -78,15 +77,15 @@ public function testNormalizePaginator() $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($paginator, null, true)->willReturn('Foo')->shouldBeCalled(); - $serializer->normalize('foo', null, ["jsonld_has_context" => true, "jsonld_sub_level" => true, "resource_class" => "Foo"])->willReturn(['name' => 'Kévin', 'friend' => 'Smail']); $iriConvert = $this->prophesize(IriConverterInterface::class); $contextBuilder = $this->prophesize(ContextBuilderInterface::class); - $contextBuilder->getResourceContextUri("Foo")->willReturn('/contexts/Foo'); - $iriConvert->getIriFromResourceClass("Foo")->willReturn('/foo/1'); - + $contextBuilder->getResourceContextUri('Foo')->willReturn('/contexts/Foo'); + $iriConvert->getIriFromResourceClass('Foo')->willReturn('/foo/1'); + $itemNormalizer = $this->prophesize(AbstractItemNormalizer::class); + $itemNormalizer->normalize('foo', null, ['jsonld_has_context' => true, 'api_sub_level' => true, 'resource_class' => 'Foo'])->willReturn(['name' => 'Kévin', 'friend' => 'Smail']); $normalizer = new CollectionNormalizer($contextBuilder->reveal(), $resourceClassResolverProphecy->reveal(), $iriConvert->reveal()); - $normalizer->setSerializer($serializer->reveal()); + $normalizer->setNormalizer($itemNormalizer->reveal()); $this->assertEquals(['@context' => '/contexts/Foo', '@id' => '/foo/1', '@type' => 'hydra:Collection', 'hydra:member' => [0 => ['name' => 'Kévin', 'friend' => 'Smail']], 'hydra:totalItems' => 1312.], $normalizer->normalize($paginator)); } diff --git a/tests/Hydra/Serializer/ItemNormalizerTest.php b/tests/Hydra/Serializer/ItemNormalizerTest.php new file mode 100644 index 00000000000..1653e177248 --- /dev/null +++ b/tests/Hydra/Serializer/ItemNormalizerTest.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ApiPlatform\Core\tests\Hydra; + +use ApiPlatform\Core\Api\IriConverterInterface; +use ApiPlatform\Core\Api\ResourceClassResolverInterface; +use ApiPlatform\Core\Exception\InvalidArgumentException; +use ApiPlatform\Core\JsonLd\ContextBuilderInterface; +use ApiPlatform\Core\JsonLd\Serializer\ItemNormalizer; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; +use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; +use Prophecy\Argument; +use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use Symfony\Component\Serializer\SerializerInterface; + +/** + * @author Kévin Dunglas + */ +class ItemNormalizerTest extends \PHPUnit_Framework_TestCase +{ + public function testDontSupportDenormalization() + { + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); + $resourceClassResolverProphecy->getResourceClass(['dummy'], 'Dummy')->willReturn(Dummy::class); + $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['name' => 'name'])); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn(new PropertyMetadata())->shouldBeCalled(1); + + $normalizer = new ItemNormalizer($resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), $contextBuilderProphecy->reveal()); + + $this->assertFalse($normalizer->supportsDenormalization('foo', ItemNormalizer::FORMAT)); + $normalizer->denormalize(['foo'], Dummy::class, 'jsonld', ['jsonld_has_context' => true, 'jsonld_sub_level' => true, 'resource_class' => Dummy::class]); + } + + public function testSupportNormalization() + { + $std = new \stdClass(); + $dummy = new Dummy(); + $dummy->setDescription('hello'); + + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); + $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); + + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->getResourceClass($dummy)->willReturn(Dummy::class)->shouldBeCalled(); + $resourceClassResolverProphecy->getResourceClass($std)->willThrow(new InvalidArgumentException())->shouldBeCalled(); + + $normalizer = new ItemNormalizer( + $resourceMetadataFactoryProphecy->reveal(), + $propertyNameCollectionFactoryProphecy->reveal(), + $propertyMetadataFactoryProphecy->reveal(), + $iriConverterProphecy->reveal(), + $resourceClassResolverProphecy->reveal(), + $contextBuilderProphecy->reveal() + ); + + $this->assertTrue($normalizer->supportsNormalization($dummy, 'jsonld')); + $this->assertFalse($normalizer->supportsNormalization($dummy, 'xml')); + $this->assertFalse($normalizer->supportsNormalization($std, 'jsonld')); + } + + public function testNormalize() + { + $dummy = new Dummy(); + $dummy->setName('hello'); + + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $propertyNameCollection = new PropertyNameCollection(['name']); + $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn($propertyNameCollection)->shouldBeCalled(); + + $propertyMetadataFactory = new PropertyMetadata(null, null, true); + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadataFactory)->shouldBeCalled(); + + $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); + $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1988')->shouldBeCalled(); + + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->getResourceClass($dummy, null, true)->willReturn(Dummy::class)->shouldBeCalled(); + + $serializerProphecy = $this->prophesize(SerializerInterface::class); + $serializerProphecy->willImplement(NormalizerInterface::class); + $serializerProphecy->normalize('hello', null, Argument::type('array'))->willReturn('hello')->shouldBeCalled(); + $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); + $contextBuilderProphecy->getResourceContextUri(Dummy::class)->willReturn('/contexts/Dummy'); + + $normalizer = new ItemNormalizer( + $resourceMetadataFactoryProphecy->reveal(), + $propertyNameCollectionFactoryProphecy->reveal(), + $propertyMetadataFactoryProphecy->reveal(), + $iriConverterProphecy->reveal(), + $resourceClassResolverProphecy->reveal(), + $contextBuilderProphecy->reveal() + ); + $normalizer->setSerializer($serializerProphecy->reveal()); + + $expected = ['@context' => '/contexts/Dummy', + '@id' => '/dummies/1988', + '@type' => 'Dummy', + 'name' => 'hello', + + + ]; + $this->assertEquals($expected, $normalizer->normalize($dummy)); + } +} From a068efc1ed2cc7c38f2d00b9ffdce340f3f9b529 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Fri, 15 Jul 2016 22:42:45 +0200 Subject: [PATCH 3/3] feat: Hydra - add apiDocumentationBuilder and remove deps on contextBuilder --- .../Symfony/Bundle/Resources/config/hydra.xml | 1 - src/Hydra/ApiDocumentationBuilder.php | 12 +- tests/Hydra/ApiDocumentationBuilderTest.php | 252 ++++++++++++++++++ tests/Swagger/ApiDocumentationBuilderTest.php | 2 +- 4 files changed, 258 insertions(+), 9 deletions(-) create mode 100644 tests/Hydra/ApiDocumentationBuilderTest.php diff --git a/src/Bridge/Symfony/Bundle/Resources/config/hydra.xml b/src/Bridge/Symfony/Bundle/Resources/config/hydra.xml index 995b0966e6b..4e0d747a46d 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/hydra.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/hydra.xml @@ -17,7 +17,6 @@ - diff --git a/src/Hydra/ApiDocumentationBuilder.php b/src/Hydra/ApiDocumentationBuilder.php index 636a7912731..d9a8cde2ef1 100644 --- a/src/Hydra/ApiDocumentationBuilder.php +++ b/src/Hydra/ApiDocumentationBuilder.php @@ -35,20 +35,18 @@ final class ApiDocumentationBuilder implements ApiDocumentationBuilderInterface private $resourceMetadataFactory; private $propertyNameCollectionFactory; private $propertyMetadataFactory; - private $contextBuilder; private $resourceClassResolver; private $operationMethodResolver; private $urlGenerator; private $title; private $description; - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ContextBuilderInterface $contextBuilder, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '') + public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '') { $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; $this->resourceMetadataFactory = $resourceMetadataFactory; $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->contextBuilder = $contextBuilder; $this->resourceClassResolver = $resourceClassResolver; $this->operationMethodResolver = $operationMethodResolver; $this->urlGenerator = $urlGenerator; @@ -404,9 +402,10 @@ private function getRange(PropertyMetadata $propertyMetadata) */ private function getContext() : array { - return array_merge( - $this->contextBuilder->getBaseContext(UrlGeneratorInterface::ABS_URL), + return [ + '@vocab' => $this->urlGenerator->generate('api_hydra_doc', [], UrlGeneratorInterface::ABS_URL).'#', + 'hydra' => ContextBuilderInterface::HYDRA_NS, 'rdf' => ContextBuilderInterface::RDF_NS, 'rdfs' => ContextBuilderInterface::RDFS_NS, 'xmls' => ContextBuilderInterface::XML_NS, @@ -416,7 +415,6 @@ private function getContext() : array 'subClassOf' => ['@id' => 'rdfs:subClassOf', '@type' => '@id'], 'expects' => ['@id' => 'hydra:expects', '@type' => '@id'], 'returns' => ['@id' => 'hydra:returns', '@type' => '@id'], - ] - ); + ]; } } diff --git a/tests/Hydra/ApiDocumentationBuilderTest.php b/tests/Hydra/ApiDocumentationBuilderTest.php new file mode 100644 index 00000000000..345ebc143bc --- /dev/null +++ b/tests/Hydra/ApiDocumentationBuilderTest.php @@ -0,0 +1,252 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ApiPlatform\Core\Tests\Hydra; + +use ApiPlatform\Core\Api\OperationMethodResolverInterface; +use ApiPlatform\Core\Api\ResourceClassResolverInterface; +use ApiPlatform\Core\Api\UrlGeneratorInterface; +use ApiPlatform\Core\Hydra\ApiDocumentationBuilder; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; +use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; +use Prophecy\Argument; +use Symfony\Component\PropertyInfo\Type; + +/** + * @author Amrouche Hamza + */ +class ApiDocumentationBuilderTest extends \PHPUnit_Framework_TestCase /**/ +{ + public function testGetApiDocumention() + { + $title = 'Test Api'; + $desc = 'test ApiGerard'; + $formats = ['jsonld' => ['application/ld+json']]; + + $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); + $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummy' => 'dummy']))->shouldBeCalled(); + + $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + $propertyNameCollectionFactoryProphecy->create('dummy', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['name'])); + + $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); + + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $propertyMetadataFactoryProphecy->create('dummy', 'name')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'name', true, true, true, true, false, false, null, [])); + + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(true); + + $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); + $operationMethodResolverProphecy->getItemOperationMethod('dummy', 'get')->shouldBeCalled()->willReturn('GET'); + $operationMethodResolverProphecy->getItemOperationMethod('dummy', 'put')->shouldBeCalled()->willReturn('PUT'); + $operationMethodResolverProphecy->getCollectionOperationMethod('dummy', 'get')->shouldBeCalled()->willReturn('GET'); + $operationMethodResolverProphecy->getCollectionOperationMethod('dummy', 'post')->shouldBeCalled()->willReturn('POST'); + + $urlGenerator = $this->prophesize(UrlGeneratorInterface::class); + $urlGenerator->generate('api_hydra_doc')->willReturn('/doc')->shouldBeCalled(1); + $urlGenerator->generate('api_hydra_entrypoint')->willReturn('/')->shouldBeCalled(1); + + $urlGenerator->generate('api_hydra_doc', [], UrlGeneratorInterface::ABS_URL)->willReturn('/doc')->shouldBeCalled(1); + + $apiDocumentationBuilder = new ApiDocumentationBuilder( + $resourceNameCollectionFactoryProphecy->reveal(), + $resourceMetadataFactoryProphecy->reveal(), + $propertyNameCollectionFactoryProphecy->reveal(), + $propertyMetadataFactoryProphecy->reveal(), + $resourceClassResolverProphecy->reveal(), + $operationMethodResolverProphecy->reveal(), + $urlGenerator->reveal(), + $title, + $desc); + + $expected = [ + '@context' => [ + '@vocab' => '/doc#', + 'hydra' => 'http://www.w3.org/ns/hydra/core#', + 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', + 'xmls' => 'http://www.w3.org/2001/XMLSchema#', + 'owl' => 'http://www.w3.org/2002/07/owl#', + 'domain' => [ + '@id' => 'rdfs:domain', + '@type' => '@id', + ], + 'range' => [ + '@id' => 'rdfs:range', + '@type' => '@id', + ], + 'subClassOf' => [ + '@id' => 'rdfs:subClassOf', + '@type' => '@id', + ], + 'expects' => [ + '@id' => 'hydra:expects', + '@type' => '@id', + ], + 'returns' => [ + '@id' => 'hydra:returns', + '@type' => '@id', + ], + ], + '@id' => '/doc', + 'hydra:title' => 'Test Api', + 'hydra:description' => 'test ApiGerard', + 'hydra:supportedClass' => [ + 0 => [ + '@id' => '#dummy', + '@type' => 'hydra:Class', + 'rdfs:label' => 'dummy', + 'hydra:title' => 'dummy', + 'hydra:description' => 'dummy', + 'hydra:supportedProperty' => [0 => [ + '@type' => 'hydra:SupportedProperty', + 'hydra:property' => [ + '@id' => '#dummy/name', + '@type' => 'rdf:Property', + 'rdfs:label' => 'name', + 'domain' => '#dummy', + 'range' => 'xmls:string', + ], + 'hydra:title' => 'name', + 'hydra:required' => false, + 'hydra:readable' => true, + 'hydra:writable' => true, + 'hydra:description' => 'name', + ]], + 'hydra:supportedOperation' => [ + 0 => [ + '@type' => 'hydra:Operation', + 'hydra:method' => 'GET', + 'hydra:title' => 'Retrieves dummy resource.', + 'rdfs:label' => 'Retrieves dummy resource.', + 'returns' => '#dummy', + ], + 1 => [ + '@type' => 'hydra:ReplaceResourceOperation', + 'expects' => '#dummy', + 'hydra:method' => 'PUT', + 'hydra:title' => 'Replaces the dummy resource.', + 'rdfs:label' => 'Replaces the dummy resource.', + 'returns' => '#dummy', + ], + ], + ], + 1 => [ + '@id' => '#Entrypoint', + '@type' => 'hydra:Class', + 'hydra:title' => 'The API entrypoint', + 'hydra:supportedProperty' => [0 => [ + '@type' => 'hydra:SupportedProperty', + 'hydra:property' => [ + '@id' => '#Entrypoint/dummy', + '@type' => 'hydra:Link', + 'rdfs:label' => 'The collection of dummy resources', + 'domain' => '#Entrypoint', + 'range' => 'hydra:PagedCollection', + 'hydra:supportedOperation' => [ + 0 => [ + '@type' => 'hydra:Operation', + 'hydra:method' => 'GET', + 'hydra:title' => 'Retrieves the collection of dummy resources.', + 'rdfs:label' => 'Retrieves the collection of dummy resources.', + 'returns' => 'hydra:PagedCollection', + ], + 1 => [ + '@type' => 'hydra:CreateResourceOperation', + 'expects' => '#dummy', + 'hydra:method' => 'POST', + 'hydra:title' => 'Creates a dummy resource.', + 'rdfs:label' => 'Creates a dummy resource.', + 'returns' => '#dummy', + ], + ], + ], + 'hydra:title' => 'The collection of dummy resources', + 'hydra:readable' => true, + 'hydra:writable' => false, + ]], + 'hydra:supportedOperation' => [ + '@type' => 'hydra:Operation', + 'hydra:method' => 'GET', + 'rdfs:label' => 'The API entrypoint.', + 'returns' => '#EntryPoint', + ], + ], + 2 => [ + '@id' => '#ConstraintViolation', + '@type' => 'hydra:Class', + 'hydra:title' => 'A constraint violation', + 'hydra:supportedProperty' => [ + 0 => ['@type' => 'hydra:SupportedProperty', + 'hydra:property' => [ + '@id' => '#ConstraintViolation/propertyPath', + '@type' => 'rdf:Property', + 'rdfs:label' => 'propertyPath', + 'domain' => '#ConstraintViolation', + 'range' => 'xmls:string', + ], + 'hydra:title' => 'propertyPath', + 'hydra:description' => 'The property path of the violation', + 'hydra:readable' => true, + 'hydra:writable' => false, + ], + 1 => [ + '@type' => 'hydra:SupportedProperty', + 'hydra:property' => [ + '@id' => '#ConstraintViolation/message', + '@type' => 'rdf:Property', + 'rdfs:label' => 'message', + 'domain' => '#ConstraintViolation', + 'range' => 'xmls:string', + ], + 'hydra:title' => 'message', + 'hydra:description' => 'The message associated with the violation', + 'hydra:readable' => true, + 'hydra:writable' => false, + ], + ], + ], + 3 => [ + '@id' => '#ConstraintViolationList', + '@type' => 'hydra:Class', + 'subClassOf' => 'hydra:Error', + 'hydra:title' => 'A constraint violation list', + 'hydra:supportedProperty' => [0 => [ + '@type' => 'hydra:SupportedProperty', + 'hydra:property' => [ + '@id' => '#ConstraintViolationList/violation', + '@type' => 'rdf:Property', + 'rdfs:label' => 'violation', + 'domain' => '#ConstraintViolationList', + 'range' => '#ConstraintViolation', + ], + 'hydra:title' => 'violation', + 'hydra:description' => 'The violations', + 'hydra:readable' => true, + 'hydra:writable' => false, + ]], + ], + ], + 'hydra:entrypoint' => '/', + + ]; + $this->assertEquals($expected, $apiDocumentationBuilder->getApiDocumentation()); + } +} diff --git a/tests/Swagger/ApiDocumentationBuilderTest.php b/tests/Swagger/ApiDocumentationBuilderTest.php index 6cebc019f56..7dfadfa7317 100644 --- a/tests/Swagger/ApiDocumentationBuilderTest.php +++ b/tests/Swagger/ApiDocumentationBuilderTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace ApiPlatform\Core\tests\Swagger; +namespace ApiPlatform\Core\Tests\Swagger; use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Api\OperationMethodResolverInterface;