mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-25 16:14:59 +00:00
Add integration and unit tests for PersonJsonNormalizer
to verify normalization behavior
- Introduce `PersonJsonNormalizerIntegrationTest` to test database-driven normalization scenarios. - Expand `PersonJsonNormalizerTest` with cases covering minimal group normalization and extended keys. - Refactor test setup to use mock objects and improve coverage of normalization logic.
This commit is contained in:
@@ -78,11 +78,6 @@ class PersonJsonNormalizer implements NormalizerAwareInterface, NormalizerInterf
|
||||
null];
|
||||
}
|
||||
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return Person::class === $type && 'person' === ($data['type'] ?? null);
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return $data instanceof Person && 'json' === $format;
|
||||
|
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Serializer\Normalizer;
|
||||
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
final class PersonJsonNormalizerIntegrationTest extends KernelTestCase
|
||||
{
|
||||
public function testNormalizeExistingPersonFromDatabase(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
$container = self::getContainer();
|
||||
|
||||
/** @var PersonRepository $repo */
|
||||
$repo = $container->get(PersonRepository::class);
|
||||
$person = $repo->findOneBy([]);
|
||||
|
||||
if (!$person instanceof Person) {
|
||||
self::markTestSkipped('No person found in test database. Load fixtures to enable this test.');
|
||||
}
|
||||
|
||||
/** @var SerializerInterface $serializer */
|
||||
$serializer = $container->get(SerializerInterface::class);
|
||||
|
||||
// Should not throw
|
||||
$data = $serializer->normalize($person, 'json');
|
||||
Assert::assertIsArray($data);
|
||||
|
||||
// Spot check some expected keys exist
|
||||
foreach ([
|
||||
'type', 'id', 'text', 'textAge', 'firstName', 'lastName', 'birthdate', 'age', 'gender', 'civility',
|
||||
] as $key) {
|
||||
Assert::assertArrayHasKey($key, $data, sprintf('Expected key %s in normalized payload', $key));
|
||||
}
|
||||
|
||||
// Minimal group should also work
|
||||
$minimal = $serializer->normalize($person, 'json', ['groups' => 'minimal']);
|
||||
Assert::assertIsArray($minimal);
|
||||
foreach ([
|
||||
'type', 'id', 'text', 'textAge', 'firstName', 'lastName',
|
||||
] as $key) {
|
||||
Assert::assertArrayHasKey($key, $minimal, sprintf('Expected key %s in minimal normalized payload', $key));
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,74 +11,179 @@ declare(strict_types=1);
|
||||
|
||||
namespace Serializer\Normalizer;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Phonenumber\PhoneNumberHelperInterface;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
|
||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\PersonBundle\Entity\PersonAltName;
|
||||
use Chill\PersonBundle\Repository\ResidentialAddressRepository;
|
||||
use Chill\PersonBundle\Serializer\Normalizer\PersonJsonNormalizer;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
* @covers \Chill\PersonBundle\Serializer\Normalizer\PersonJsonNormalizer
|
||||
*/
|
||||
final class PersonJsonNormalizerTest extends KernelTestCase
|
||||
final class PersonJsonNormalizerTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private PersonJsonNormalizer $normalizer;
|
||||
|
||||
protected function setUp(): void
|
||||
public function testSupportsNormalization(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
$normalizer = $this->createNormalizer();
|
||||
|
||||
$residentialAddressRepository = $this->prophesize(ResidentialAddressRepository::class);
|
||||
$residentialAddressRepository
|
||||
->findCurrentResidentialAddressByPerson(Argument::type(Person::class), Argument::any())
|
||||
->willReturn([]);
|
||||
|
||||
$this->normalizer = $this->buildPersonJsonNormalizer(
|
||||
self::getContainer()->get(ChillEntityRenderExtension::class),
|
||||
self::getContainer()->get(PersonRepository::class),
|
||||
self::getContainer()->get(CenterResolverManagerInterface::class),
|
||||
$residentialAddressRepository->reveal(),
|
||||
self::getContainer()->get(PhoneNumberHelperInterface::class),
|
||||
self::getContainer()->get(NormalizerInterface::class)
|
||||
);
|
||||
self::assertTrue($normalizer->supportsNormalization(new Person(), 'json'));
|
||||
self::assertFalse($normalizer->supportsNormalization(new \stdClass(), 'json'));
|
||||
self::assertFalse($normalizer->supportsNormalization(new Person(), 'xml'));
|
||||
}
|
||||
|
||||
public function testNormalization()
|
||||
public function testNormalizeWithMinimalGroupReturnsOnlyBaseKeys(): void
|
||||
{
|
||||
$person = new Person();
|
||||
$result = $this->normalizer->normalize($person, 'json', [AbstractNormalizer::GROUPS => ['read']]);
|
||||
$person = $this->createSamplePerson();
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$normalizer = $this->createNormalizer();
|
||||
$data = $normalizer->normalize($person, 'json', [AbstractNormalizer::GROUPS => 'minimal']);
|
||||
|
||||
// Expected base keys
|
||||
$expectedKeys = [
|
||||
'type',
|
||||
'id',
|
||||
'text',
|
||||
'textAge',
|
||||
'firstName',
|
||||
'lastName',
|
||||
'current_household_address',
|
||||
'birthdate',
|
||||
'deathdate',
|
||||
'age',
|
||||
'phonenumber',
|
||||
'mobilenumber',
|
||||
'email',
|
||||
'gender',
|
||||
'civility',
|
||||
];
|
||||
|
||||
foreach ($expectedKeys as $key) {
|
||||
self::assertArrayHasKey($key, $data, sprintf('Key %s should be present', $key));
|
||||
}
|
||||
|
||||
// Ensure extended keys are not present in minimal mode
|
||||
foreach (['centers', 'altNames', 'current_household_id', 'current_residential_addresses'] as $key) {
|
||||
self::assertArrayNotHasKey($key, $data, sprintf('Key %s should NOT be present in minimal group', $key));
|
||||
}
|
||||
}
|
||||
|
||||
private function buildPersonJsonNormalizer(
|
||||
ChillEntityRenderExtension $render,
|
||||
PersonRepository $repository,
|
||||
CenterResolverManagerInterface $centerResolverManager,
|
||||
ResidentialAddressRepository $residentialAddressRepository,
|
||||
PhoneNumberHelperInterface $phoneNumberHelper,
|
||||
NormalizerInterface $normalizer,
|
||||
): PersonJsonNormalizer {
|
||||
$personJsonNormalizer = new PersonJsonNormalizer(
|
||||
$render,
|
||||
$repository,
|
||||
$centerResolverManager,
|
||||
$residentialAddressRepository,
|
||||
$phoneNumberHelper
|
||||
);
|
||||
$personJsonNormalizer->setNormalizer($normalizer);
|
||||
public function testNormalizeWithoutGroupsIncludesExtendedKeys(): void
|
||||
{
|
||||
$person = $this->createSamplePerson(withAltNames: true);
|
||||
|
||||
return $personJsonNormalizer;
|
||||
$center1 = (new Center())->setName('c1');
|
||||
$center2 = (new Center())->setName('c2');
|
||||
|
||||
|
||||
$normalizer = $this->createNormalizer(
|
||||
centers: [$center1, $center2],
|
||||
currentResidentialAddresses: [['addr' => 1]],
|
||||
);
|
||||
|
||||
$data = $normalizer->normalize($person, 'json');
|
||||
|
||||
// Base keys
|
||||
$baseKeys = [
|
||||
'type', 'id', 'text', 'textAge', 'firstName', 'lastName', 'current_household_address', 'birthdate', 'deathdate', 'age', 'phonenumber', 'mobilenumber', 'email', 'gender', 'civility',
|
||||
];
|
||||
foreach ($baseKeys as $key) {
|
||||
self::assertArrayHasKey($key, $data, sprintf('Key %s should be present', $key));
|
||||
}
|
||||
|
||||
// Extended keys
|
||||
foreach (['centers', 'altNames', 'current_household_id', 'current_residential_addresses'] as $key) {
|
||||
self::assertArrayHasKey($key, $data, sprintf('Key %s should be present', $key));
|
||||
}
|
||||
|
||||
self::assertSame(['c1', 'c2'], $data['centers']);
|
||||
self::assertIsArray($data['altNames']);
|
||||
self::assertSame([['key' => 'aka', 'label' => 'Johnny']], $data['altNames']);
|
||||
self::assertNull($data['current_household_id'], 'No household set so id should be null');
|
||||
self::assertSame([['addr' => 1]], $data['current_residential_addresses']);
|
||||
}
|
||||
|
||||
private function createNormalizer(array $centers = [], array $currentResidentialAddresses = []): PersonJsonNormalizer
|
||||
{
|
||||
$render = $this->prophesize(ChillEntityRenderExtension::class);
|
||||
$render->renderString(Argument::type(Person::class), ['addAge' => false])->willReturn('John Doe');
|
||||
$render->renderString(Argument::type(Person::class), ['addAge' => true])->willReturn('John Doe (25)');
|
||||
|
||||
$centerResolver = $this->prophesize(CenterResolverManagerInterface::class);
|
||||
$centerResolver->resolveCenters(Argument::type(Person::class))->willReturn($centers);
|
||||
|
||||
$raRepo = $this->prophesize(ResidentialAddressRepository::class);
|
||||
$raRepo->findCurrentResidentialAddressByPerson(Argument::type(Person::class))->willReturn($currentResidentialAddresses);
|
||||
|
||||
$phoneHelper = $this->prophesize(PhoneNumberHelperInterface::class);
|
||||
|
||||
$normalizer = new PersonJsonNormalizer(
|
||||
$render->reveal(),
|
||||
$centerResolver->reveal(),
|
||||
$raRepo->reveal(),
|
||||
$phoneHelper->reveal(),
|
||||
);
|
||||
|
||||
// Inner normalizer that echoes values or simple conversions
|
||||
$inner = new class () implements NormalizerInterface {
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
// For scalars and arrays, return as-is; for objects, return string or id when possible
|
||||
if (\is_scalar($object) || null === $object) {
|
||||
return $object;
|
||||
}
|
||||
if ($object instanceof \DateTimeInterface) {
|
||||
return $object->format('Y-m-d');
|
||||
}
|
||||
if ($object instanceof Center) {
|
||||
return $object->getName();
|
||||
}
|
||||
if (is_array($object)) {
|
||||
return array_map(fn ($o) => $this->normalize($o, $format, $context), $object);
|
||||
}
|
||||
|
||||
// default stub
|
||||
return (string) (method_exists($object, 'getId') ? $object->getId() : 'normalized');
|
||||
}
|
||||
};
|
||||
|
||||
$normalizer->setNormalizer($inner);
|
||||
|
||||
return $normalizer;
|
||||
}
|
||||
|
||||
private function createSamplePerson(bool $withAltNames = false): Person
|
||||
{
|
||||
$p = new Person();
|
||||
$p->setFirstName('John');
|
||||
$p->setLastName('Doe');
|
||||
$p->setBirthdate(new \DateTime('2000-01-01'));
|
||||
$p->setEmail('john@example.test');
|
||||
|
||||
if ($withAltNames) {
|
||||
$alt = new PersonAltName();
|
||||
$alt->setKey('aka');
|
||||
$alt->setLabel('Johnny');
|
||||
$p->setAltNames(new ArrayCollection([$alt]));
|
||||
}
|
||||
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user