Skip to content

Commit

Permalink
Implement integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
barw4 committed Oct 18, 2024
1 parent 9d014ce commit 3318577
Show file tree
Hide file tree
Showing 36 changed files with 731 additions and 124 deletions.
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6180,11 +6180,6 @@ parameters:
count: 1
path: tests/lib/Output/ValueObjectVisitorBaseTest.php

-
message: "#^Method Ibexa\\\\Tests\\\\Rest\\\\Output\\\\VisitorTest\\:\\:testSetFilteredHeaders\\(\\) has no return type specified\\.$#"
count: 1
path: tests/lib/Output/VisitorTest.php

-
message: "#^Method Ibexa\\\\Tests\\\\Rest\\\\Server\\\\Input\\\\Parser\\\\BaseTest\\:\\:getParseHrefExpectationsMap\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
Expand Down
3 changes: 2 additions & 1 deletion phpunit.integration.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
beStrictAboutTodoAnnotatedTests="true"
verbose="true">
<php>
<env name="setupFactory" value="\Ibexa\Contracts\Core\Test\Repository\SetupFactory\Legacy" />
<env name="KERNEL_CLASS" value="Ibexa\Tests\Integration\Rest\IbexaTestKernel" />
<env name="SEARCH_ENGINE" value="legacy" />
<env name="DATABASE_URL" value="sqlite://i@i/var/test.db" />
<env name="DATABASE_URL" value="sqlite://i@i/test.db" />
<env name="SYMFONY_DEPRECATIONS_HELPER" value="max[self]=4&amp;max[direct]=0&amp;verbose=0"/>
</php>
<testsuites>
Expand Down
2 changes: 2 additions & 0 deletions src/bundle/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,8 @@ services:

Ibexa\Contracts\Rest\Output\VisitorAdapterNormalizer:
arguments:
$jsonEncoder: '@ibexa.rest.serializer.encoder.json'
$xmlEncoder: '@ibexa.rest.serializer.encoder.xml'
$valueObjectVisitorResolver: '@Ibexa\Contracts\Rest\Output\ValueObjectVisitorResolver'
tags:
- { name: ibexa.rest.serializer.normalizer, priority: -1000 }
Expand Down
43 changes: 35 additions & 8 deletions src/contracts/Output/VisitorAdapterNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

namespace Ibexa\Contracts\Rest\Output;

use Ibexa\Contracts\Rest\Output\Generator as BaseGenerator;
use Ibexa\Rest\Output\Generator;
use LogicException;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
Expand All @@ -22,9 +25,9 @@ final class VisitorAdapterNormalizer implements NormalizerInterface, NormalizerA

public const string ENCODER_CONTEXT = 'ENCODER_CONTEXT';

public const string OUTER_ELEMENT = 'outer_element';

public function __construct(
private readonly EncoderInterface $jsonEncoder,
private readonly EncoderInterface $xmlEncoder,
private readonly ValueObjectVisitorResolverInterface $valueObjectVisitorResolver,
) {
}
Expand Down Expand Up @@ -90,11 +93,7 @@ private function visitValueObject(
?string $format,
array $context,
): array {
if (!isset($context['visitor'])) {
throw new LogicException('Context must have the "Visitor" instance passed.');
}

$visitor = $context['visitor'];
$visitor = $context['visitor'] ?? $this->createVisitor($format);
$generator = $visitor->getGenerator();

$generator->reset();
Expand Down Expand Up @@ -125,9 +124,37 @@ private function buildContext(array $context, ?string $format): array
$context += [self::CALLED_CONTEXT => true];

if ($format === 'xml') {
$context += [self::OUTER_ELEMENT => true];
$context += [Generator\InMemory\Xml::OUTER_ELEMENT => true];
}

return $context;
}

private function createGenerator(string $format): BaseGenerator
{
if ($format === 'xml') {
return new Generator\InMemory\Xml(
new Generator\InMemory\Xml\FieldTypeHashGenerator($this->normalizer),
);
}

return new Generator\Json(
new Generator\Json\FieldTypeHashGenerator($this->normalizer),
);
}

private function createVisitor(?string $format): Visitor
{
$format = $format ?: 'json';

$generator = $this->createGenerator($format);

return new Visitor(
$generator,
$this->normalizer,
$format === 'xml' ? $this->xmlEncoder : $this->jsonEncoder,
$this->valueObjectVisitorResolver,
$format,
);
}
}
15 changes: 4 additions & 11 deletions src/lib/Output/Generator/InMemory/Xml.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

namespace Ibexa\Rest\Output\Generator\InMemory;

use Ibexa\Contracts\Rest\Output\VisitorAdapterNormalizer;
use Ibexa\Rest\Output\Generator\Data;
use Ibexa\Rest\Output\Generator\Data\ArrayList;
use Ibexa\Rest\Output\Generator\Json;
Expand All @@ -21,6 +20,8 @@

final class Xml extends Json
{
public const string OUTER_ELEMENT = 'outer_element';

public function getMediaType($name): string
{
return $this->generateMediaTypeWithVendor($name, 'xml', $this->vendor);
Expand All @@ -36,10 +37,6 @@ public function startList($name): void
$this->json = $array;
}

/**
* @param string $name
* @param string $value
*/
public function startAttribute($name, $value): void
{
$this->checkStartAttribute($name);
Expand Down Expand Up @@ -74,11 +71,6 @@ public function startValueElement(string $name, $value, array $attributes = []):
}
}

/**
* End document.
*
* Returns the generated document as a string.
*/
public function endDocument(mixed $data): string
{
parent::endDocument($data);
Expand Down Expand Up @@ -111,7 +103,8 @@ public function getEncoderContext(array $data): array
XmlEncoder::VERSION => '1.0',
XmlEncoder::ENCODING => 'UTF-8',
XmlEncoder::AS_COLLECTION => true,
VisitorAdapterNormalizer::OUTER_ELEMENT => true,
XmlEncoder::FORMAT_OUTPUT => true,
self::OUTER_ELEMENT => true,
];
}
}
14 changes: 3 additions & 11 deletions src/lib/Output/Generator/InMemory/Xml/FieldTypeHashGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ protected function generateValue($parent, $value): mixed
}
}

protected function generateArrayValue($parent, $value)
protected function generateArrayValue($parent, $value): JsonObject
{
if ($this->isNumericArray($value)) {
return $this->generateListArray($parent, $value);
Expand All @@ -39,7 +39,7 @@ protected function generateArrayValue($parent, $value)
}
}

protected function generateListArray($parent, array $listArray)
protected function generateListArray($parent, array $listArray): JsonObject
{
$object = new JsonObject($parent);

Expand All @@ -55,15 +55,7 @@ protected function generateListArray($parent, array $listArray)
return $object;
}

/**
* Generates a JSON object from the given $hashArray with $parent.
*
* @param \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject $parent
* @param array<mixed> $hashArray
*
* @return \Ibexa\Rest\Output\Generator\Json\JsonObject
*/
protected function generateHashArray($parent, array $hashArray)
protected function generateHashArray($parent, array $hashArray): JsonObject
{
$object = new JsonObject($parent);

Expand Down
6 changes: 3 additions & 3 deletions src/lib/Output/Normalizer/JsonObjectNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

namespace Ibexa\Rest\Output\Normalizer;

use Ibexa\Contracts\Rest\Output\VisitorAdapterNormalizer;
use Ibexa\Rest\Output\Generator\Data\ArrayList;
use Ibexa\Rest\Output\Generator\InMemory;
use Ibexa\Rest\Output\Generator\Json\JsonObject;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
Expand All @@ -27,8 +27,8 @@ public function normalize($object, ?string $format = null, array $context = []):
{
$vars = get_object_vars($object);

$isOuterElement = $context[VisitorAdapterNormalizer::OUTER_ELEMENT] ?? false;
unset($context[VisitorAdapterNormalizer::OUTER_ELEMENT]);
$isOuterElement = $context[InMemory\Xml::OUTER_ELEMENT] ?? false;
unset($context[InMemory\Xml::OUTER_ELEMENT]);

$data = [];
foreach ($vars as $key => $value) {
Expand Down
14 changes: 14 additions & 0 deletions tests/integration/IbexaTestKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Serializer\Serializer;

final class IbexaTestKernel extends CoreIbexaTestKernel
{
Expand Down Expand Up @@ -45,6 +46,12 @@ protected static function getExposedServicesByClass(): iterable
yield UriParserInterface::class;
}

protected static function getExposedServicesById(): iterable
{
yield from parent::getExposedServicesById();
yield 'ibexa.rest.serializer' => Serializer::class;
}

private static function loadRouting(ContainerBuilder $container): void
{
$container->loadFromExtension('framework', [
Expand All @@ -53,4 +60,11 @@ private static function loadRouting(ContainerBuilder $container): void
],
]);
}

protected function loadServices(LoaderInterface $loader): void
{
parent::loadServices($loader);

$loader->load(__DIR__ . '/Resources/services.yaml');
}
}
4 changes: 4 additions & 0 deletions tests/integration/Resources/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
services:
Ibexa\Tests\Integration\Rest\Serializer\TestDataObjectNormalizer:
tags:
- { name: ibexa.rest.serializer.normalizer }
108 changes: 108 additions & 0 deletions tests/integration/Serializer/SerializerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

Check warning on line 1 in tests/integration/Serializer/SerializerTest.php

View workflow job for this annotation

GitHub Actions / Run code style check

Found violation(s) of type: no_unused_imports

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Tests\Integration\Rest\Serializer;

use Ibexa\Contracts\Core\Repository\LocationService;
use Ibexa\Contracts\Test\Core\IbexaKernelTestCase;
use Ibexa\Tests\Bundle\Rest\Functional\ResourceAssertionsTrait;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Serializer;

final class SerializerTest extends IbexaKernelTestCase
{
use ResourceAssertionsTrait;

private const SNAPSHOT_DIR = __DIR__ . '/_snapshot';

private Serializer $serializer;

private LocationService $locationService;

protected function setUp(): void
{
parent::setUp();

$this->serializer = $this->getIbexaTestCore()->getServiceByClassName(
Serializer::class,
'ibexa.rest.serializer',
);
$this->locationService = $this->getIbexaTestCore()->getServiceByClassName(
LocationService::class,
);
}

public function testSerializeTestDataObject(): void
{
$dataObject = new TestDataObject(
'some_string',
1,
);

$expectedData = [
'string' => 'some_string',
'int' => 1,
'innerObject' => null,
'location' => null,
];

$serializedData = $this->serializer->serialize($dataObject, 'json');

self::assertSame(json_encode($expectedData), $serializedData);
}

public function testNormalizeTestDataObjectWithApiLocation(): void
{
$dataObject = new TestDataObject(
'some_string',
1,
null,
$this->locationService->loadLocation(2),
);

$normalizedData = $this->serializer->normalize($dataObject);

self::assertSame(
'application/vnd.ibexa.api.Location+json',
$normalizedData['location']['_media-type'] ?? [],
);
self::assertSame(
'/api/ibexa/v2/content/locations/1/2',
$normalizedData['location']['_href'] ?? [],
);
self::assertSame($normalizedData['location']['id'] ?? null, 2);

self::assertArrayHasKey('Content', $normalizedData['location'] ?? []);
self::assertSame(
'application/vnd.ibexa.api.Content+json',
$normalizedData['location']['Content']['_media-type'],
);
}

public function testSerializeTestDataObjectWithApiLocation(): void
{
$dataObject = new TestDataObject(
'some_string',
1,
null,
$this->locationService->loadLocation(2),
);

$serializedData = $this->serializer->serialize($dataObject, 'xml');
self::assertResponseMatchesXmlSnapshot(
$serializedData,
self::SNAPSHOT_DIR . '/TestDataObject.xml',
);

$serializedData = $this->serializer->serialize($dataObject, 'json');
self::assertResponseMatchesJsonSnapshot(
$serializedData,
self::SNAPSHOT_DIR . '/TestDataObject.json',
);
}
}
22 changes: 22 additions & 0 deletions tests/integration/Serializer/TestDataObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Tests\Integration\Rest\Serializer;

use Ibexa\Contracts\Core\Repository\Values\Content\Location;

final readonly class TestDataObject
{
public function __construct(
public string $string,
public int $int,
public ?self $innerObject = null,
public ?Location $apiLocation = null,
) {
}
}
Loading

0 comments on commit 3318577

Please sign in to comment.