mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-02 05:57:45 +00:00
409 lines
16 KiB
PHP
409 lines
16 KiB
PHP
<?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 Chill\TicketBundle\Tests\Serializer\Normalizer;
|
|
|
|
use Chill\MainBundle\Entity\User;
|
|
use Chill\MainBundle\Entity\UserGroup;
|
|
use Chill\PersonBundle\Entity\Person;
|
|
use Chill\TicketBundle\Entity\AddresseeHistory;
|
|
use Chill\TicketBundle\Entity\CallerHistory;
|
|
use Chill\TicketBundle\Entity\Comment;
|
|
use Chill\TicketBundle\Entity\EmergencyStatusEnum;
|
|
use Chill\TicketBundle\Entity\EmergencyStatusHistory;
|
|
use Chill\TicketBundle\Entity\Motive;
|
|
use Chill\TicketBundle\Entity\MotiveHistory;
|
|
use Chill\TicketBundle\Entity\PersonHistory;
|
|
use Chill\TicketBundle\Entity\StateEnum;
|
|
use Chill\TicketBundle\Entity\StateHistory;
|
|
use Chill\TicketBundle\Entity\Ticket;
|
|
use Chill\TicketBundle\Security\Voter\CommentVoter;
|
|
use Chill\TicketBundle\Serializer\Normalizer\TicketNormalizer;
|
|
use Prophecy\Argument;
|
|
use Prophecy\PhpUnit\ProphecyTrait;
|
|
use Prophecy\Prophecy\ObjectProphecy;
|
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
|
use Symfony\Component\Security\Core\Security;
|
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
|
|
|
/**
|
|
* @internal
|
|
*
|
|
* @coversNothing
|
|
*/
|
|
class TicketNormalizerTest extends KernelTestCase
|
|
{
|
|
use ProphecyTrait;
|
|
|
|
private ObjectProphecy $security;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->security = $this->prophesize(Security::class);
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideTickets
|
|
*/
|
|
public function testNormalize(Ticket $ticket, array $expected): void
|
|
{
|
|
$actual = $this->buildNormalizer()->normalize($ticket, 'json', ['groups' => 'read']);
|
|
self::assertEqualsCanonicalizing(array_keys($expected), array_keys($actual));
|
|
|
|
foreach (array_keys($expected) as $k) {
|
|
if ('history' === $k) {
|
|
continue;
|
|
}
|
|
self::assertEqualsCanonicalizing($expected[$k], $actual[$k], sprintf("assert the content of the '%s' key", $k));
|
|
}
|
|
|
|
self::assertArrayHasKey('history', $actual);
|
|
self::assertIsArray($actual['history']);
|
|
|
|
foreach ($actual['history'] as $k => $eventType) {
|
|
self::assertEquals($expected['history'][$k]['event_type'], $eventType['event_type']);
|
|
}
|
|
}
|
|
|
|
public static function provideTickets(): iterable
|
|
{
|
|
$t = new Ticket();
|
|
|
|
// added by action
|
|
new StateHistory(StateEnum::OPEN, $t, new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
|
|
// those are added by doctrine listeners
|
|
$t->setCreatedAt(new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
$t->setCreatedBy(new User());
|
|
$t->setUpdatedAt(new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
$t->setUpdatedBy(new User());
|
|
|
|
yield [
|
|
// this a nearly empty ticket
|
|
$t,
|
|
[
|
|
'type' => 'ticket_ticket',
|
|
'type_extended' => 'ticket_ticket:extended',
|
|
'createdAt' => $t->getCreatedAt()?->getTimestamp(),
|
|
'createdBy' => ['user'],
|
|
'id' => null,
|
|
'externalRef' => '',
|
|
'currentPersons' => [],
|
|
'currentAddressees' => [],
|
|
'currentInputs' => [],
|
|
'currentMotive' => null,
|
|
'history' => [
|
|
[
|
|
'event_type' => 'create_ticket',
|
|
],
|
|
[
|
|
'event_type' => 'state_change',
|
|
],
|
|
],
|
|
'currentState' => 'open',
|
|
'updatedAt' => $t->getUpdatedAt()->getTimestamp(),
|
|
'updatedBy' => ['user'],
|
|
'emergency' => 'no',
|
|
'caller' => null,
|
|
],
|
|
];
|
|
|
|
// ticket with more features
|
|
$ticket = new Ticket();
|
|
|
|
// added by action
|
|
new StateHistory(StateEnum::OPEN, $ticket, new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
new EmergencyStatusHistory(EmergencyStatusEnum::YES, $ticket, new \DateTimeImmutable('2024-06-16T00:00:10Z'));
|
|
|
|
// those are added by doctrine listeners
|
|
$ticket->setCreatedAt(new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
$ticket->setCreatedBy(new User());
|
|
$ticket->setUpdatedAt(new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
$ticket->setUpdatedBy(new User());
|
|
$ticket->setExternalRef('2134');
|
|
$personHistory = new PersonHistory(new Person(), $ticket, new \DateTimeImmutable('2024-04-01T12:00:00'));
|
|
$ticketHistory = new MotiveHistory(new Motive(), $ticket, new \DateTimeImmutable('2024-04-01T12:02:00'));
|
|
$comment = new Comment('blabla test', $ticket);
|
|
$comment->setCreatedAt(new \DateTimeImmutable('2024-04-01T12:04:00'));
|
|
$comment->setCreatedBy(new User());
|
|
$addresseeHistory = new AddresseeHistory(new User(), new \DateTimeImmutable('2024-04-01T12:05:00'), $ticket);
|
|
$addresseeHistory->setEndDate(new \DateTimeImmutable('2024-04-01T12:06:00'));
|
|
new AddresseeHistory(new UserGroup(), new \DateTimeImmutable('2024-04-01T12:07:00'), $ticket);
|
|
|
|
yield [
|
|
$ticket,
|
|
[
|
|
'type' => 'ticket_ticket',
|
|
'type_extended' => 'ticket_ticket:extended',
|
|
'createdAt' => $ticket->getCreatedAt()?->getTimestamp(),
|
|
'createdBy' => ['user'],
|
|
'id' => null,
|
|
'externalRef' => '2134',
|
|
'currentPersons' => ['embedded'],
|
|
'currentAddressees' => ['embedded'],
|
|
'currentInputs' => [],
|
|
'currentMotive' => ['type' => 'motive', 'id' => 0],
|
|
'history' => [
|
|
['event_type' => 'add_person'],
|
|
['event_type' => 'persons_state'],
|
|
['event_type' => 'set_motive'],
|
|
['event_type' => 'add_comment'],
|
|
['event_type' => 'addressees_state'],
|
|
['event_type' => 'addressees_state'],
|
|
['event_type' => 'addressees_state'],
|
|
['event_type' => 'create_ticket'],
|
|
['event_type' => 'state_change'],
|
|
['event_type' => 'emergency_change'],
|
|
],
|
|
'currentState' => 'open',
|
|
'updatedAt' => $ticket->getUpdatedAt()->getTimestamp(),
|
|
'updatedBy' => ['user'],
|
|
'emergency' => 'yes',
|
|
'caller' => null,
|
|
],
|
|
];
|
|
|
|
// ticket with caller
|
|
$ticket = new Ticket();
|
|
$ticket->setCreatedAt(new \DateTimeImmutable('2024-06-16T00:00:00'));
|
|
$ticket->setUpdatedAt(new \DateTimeImmutable('2024-06-16T00:00:00'));
|
|
new CallerHistory(new Person(), $ticket, new \DateTimeImmutable('2024-04-01T12:00:00'));
|
|
|
|
yield [
|
|
$ticket,
|
|
[
|
|
'type' => 'ticket_ticket',
|
|
'type_extended' => 'ticket_ticket:extended',
|
|
'createdAt' => $ticket->getCreatedAt()?->getTimestamp(),
|
|
'createdBy' => null,
|
|
'id' => null,
|
|
'externalRef' => '',
|
|
'currentPersons' => [],
|
|
'currentAddressees' => [],
|
|
'currentInputs' => [],
|
|
'currentMotive' => null,
|
|
'history' => [
|
|
['event_type' => 'set_caller'],
|
|
],
|
|
'currentState' => 'open',
|
|
'updatedAt' => $ticket->getUpdatedAt()->getTimestamp(),
|
|
'updatedBy' => null,
|
|
'emergency' => 'no',
|
|
'caller' => ['person'],
|
|
],
|
|
];
|
|
}
|
|
|
|
public function testNormalizeTicketWithCommentNotAllowed(): void
|
|
{
|
|
$ticket = new Ticket();
|
|
$comment = new Comment('Test comment', $ticket);
|
|
$comment->setCreatedAt(new \DateTimeImmutable('2024-04-01T12:04:00'));
|
|
$comment->setCreatedBy(new User());
|
|
|
|
$this->security->isGranted(CommentVoter::READ, $comment)->willReturn(false)->shouldBeCalled();
|
|
|
|
$actual = $this->buildNormalizer()->normalize($ticket, 'json', ['groups' => ['read']]);
|
|
|
|
self::assertEmpty($actual['history']);
|
|
}
|
|
|
|
public function testNormalizeTicketWithCommentAllowed(): void
|
|
{
|
|
$ticket = new Ticket();
|
|
$comment = new Comment('Test comment', $ticket);
|
|
$comment->setCreatedAt(new \DateTimeImmutable('2024-04-01T12:04:00'));
|
|
$comment->setCreatedBy(new User());
|
|
|
|
$this->security->isGranted(CommentVoter::READ, $comment)->willReturn(true)->shouldBeCalled();
|
|
|
|
$actual = $this->buildNormalizer()->normalize($ticket, 'json', ['groups' => ['read']]);
|
|
|
|
self::assertCount(1, $actual['history']);
|
|
self::assertEquals('add_comment', $actual['history'][0]['event_type']);
|
|
}
|
|
|
|
public function testNormalizeReadSimple(): void
|
|
{
|
|
// Create a ticket with some data
|
|
$ticket = new Ticket();
|
|
$ticket->setExternalRef('TEST-123');
|
|
|
|
// Add state history
|
|
new StateHistory(StateEnum::OPEN, $ticket, new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
|
|
// Add emergency status
|
|
new EmergencyStatusHistory(EmergencyStatusEnum::YES, $ticket, new \DateTimeImmutable('2024-06-16T00:00:10Z'));
|
|
|
|
// Add person
|
|
$personHistory = new PersonHistory(new Person(), $ticket, new \DateTimeImmutable('2024-04-01T12:00:00'));
|
|
|
|
// Add motive
|
|
$motiveHistory = new MotiveHistory(new Motive(), $ticket, new \DateTimeImmutable('2024-04-01T12:02:00'));
|
|
|
|
// Add comment
|
|
$comment = new Comment('Test comment', $ticket);
|
|
$comment->setCreatedAt(new \DateTimeImmutable('2024-04-01T12:04:00'));
|
|
$comment->setCreatedBy(new User());
|
|
|
|
// Add addressee
|
|
new AddresseeHistory(new User(), new \DateTimeImmutable('2024-04-01T12:05:00'), $ticket);
|
|
|
|
// Add caller
|
|
new CallerHistory(new Person(), $ticket, new \DateTimeImmutable('2024-04-01T12:00:00'));
|
|
|
|
// Set created/updated metadata
|
|
$ticket->setCreatedAt(new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
$ticket->setCreatedBy(new User());
|
|
$ticket->setUpdatedAt(new \DateTimeImmutable('2024-06-16T00:00:00Z'));
|
|
$ticket->setUpdatedBy(new User());
|
|
|
|
// Normalize with read:simple group
|
|
$actual = $this->buildNormalizer()->normalize($ticket, 'json', ['groups' => 'read:simple']);
|
|
|
|
// Expected keys in read:simple normalization
|
|
$expectedKeys = [
|
|
'type',
|
|
'type_extended',
|
|
'id',
|
|
'externalRef',
|
|
'currentPersons',
|
|
'currentAddressees',
|
|
'currentInputs',
|
|
'currentMotive',
|
|
'currentState',
|
|
'emergency',
|
|
'caller',
|
|
'createdAt',
|
|
];
|
|
|
|
// Keys that should not be present in read:simple normalization
|
|
$unexpectedKeys = [
|
|
'history',
|
|
'updatedAt',
|
|
'updatedBy',
|
|
'createdBy',
|
|
];
|
|
|
|
// Assert that all expected keys are present
|
|
foreach ($expectedKeys as $key) {
|
|
self::assertArrayHasKey($key, $actual, "Expected key '{$key}' is missing");
|
|
}
|
|
|
|
// Assert that none of the unexpected keys are present
|
|
foreach ($unexpectedKeys as $key) {
|
|
self::assertArrayNotHasKey($key, $actual, "Unexpected key '{$key}' is present");
|
|
}
|
|
|
|
// Assert specific values
|
|
self::assertEquals('ticket_ticket', $actual['type']);
|
|
self::assertEquals('ticket_ticket:simple', $actual['type_extended']);
|
|
self::assertEquals('TEST-123', $actual['externalRef']);
|
|
self::assertEquals('open', $actual['currentState']);
|
|
self::assertEquals('yes', $actual['emergency']);
|
|
}
|
|
|
|
private function buildNormalizer(): TicketNormalizer
|
|
{
|
|
$this->security->isGranted(CommentVoter::READ, Argument::type(Comment::class))
|
|
->willReturn(true);
|
|
|
|
|
|
$normalizer = $this->prophesize(NormalizerInterface::class);
|
|
|
|
// empty array
|
|
$normalizer->normalize(
|
|
Argument::that(fn ($arg) => is_array($arg) && 0 === count($arg)),
|
|
'json',
|
|
Argument::type('array')
|
|
)->willReturn([]);
|
|
|
|
// array of mixed objects
|
|
$normalizer->normalize(
|
|
Argument::that(fn ($arg) => is_array($arg) && 0 < count($arg) && is_object($arg[0] ?? null)),
|
|
'json',
|
|
Argument::type('array')
|
|
)->will(fn ($args) => array_fill(0, count($args[0]), 'embedded'));
|
|
|
|
// array of event type
|
|
$normalizer->normalize(
|
|
Argument::that(fn ($arg) => is_array($arg) && 0 < count($arg) && is_array($arg[0] ?? null) && array_key_exists('event_type', $arg[0] ?? null)),
|
|
'json',
|
|
Argument::type('array')
|
|
)->will(function ($args): array {
|
|
$events = [];
|
|
|
|
foreach ($args[0] as $event) {
|
|
$events[] = $event['event_type'];
|
|
}
|
|
|
|
return $events;
|
|
});
|
|
// array of persons
|
|
$normalizer->normalize(
|
|
Argument::that(fn ($arg) => is_array($arg) && 1 === count($arg) && array_key_exists('persons', $arg)),
|
|
'json',
|
|
['groups' => 'read']
|
|
)->will(fn ($args): array => ['persons' => []]);
|
|
// array of addresses
|
|
$normalizer->normalize(
|
|
Argument::that(fn ($arg) => is_array($arg) && 1 === count($arg) && array_key_exists('addressees', $arg)),
|
|
'json',
|
|
['groups' => 'read']
|
|
)->will(fn ($args): array => ['addressees' => []]);
|
|
// state data
|
|
$normalizer->normalize(
|
|
Argument::that(fn ($arg) => is_array($arg) && 1 === count($arg) && array_key_exists('new_state', $arg)),
|
|
'json',
|
|
['groups' => 'read']
|
|
)->will(fn ($args): array => $args[0]);
|
|
$normalizer->normalize(
|
|
Argument::that(fn ($arg) => is_array($arg) && 1 === count($arg) && array_key_exists('new_emergency', $arg)),
|
|
'json',
|
|
['groups' => 'read']
|
|
)->will(fn ($args): array => $args[0]);
|
|
$normalizer->normalize(
|
|
Argument::that(fn ($arg) => is_array($arg) && 1 === count($arg) && array_key_exists('new_caller', $arg)),
|
|
'json',
|
|
['groups' => 'read']
|
|
)->will(fn ($args): array => ['new_caller' => ['dummy']]);
|
|
|
|
// datetime
|
|
$normalizer->normalize(Argument::type(\DateTimeImmutable::class), 'json', Argument::type('array'))
|
|
->will(fn ($args) => $args[0]->getTimestamp());
|
|
// user
|
|
$normalizer->normalize(Argument::type(User::class), 'json', Argument::type('array'))
|
|
->willReturn(['user']);
|
|
// person
|
|
$normalizer->normalize(Argument::type(Person::class), 'json', Argument::type('array'))
|
|
->willReturn(['person']);
|
|
// motive
|
|
$normalizer->normalize(Argument::type(Motive::class), 'json', Argument::type('array'))->willReturn(['type' => 'motive', 'id' => 0]);
|
|
// person history
|
|
$normalizer->normalize(Argument::type(PersonHistory::class), 'json', Argument::type('array'))
|
|
->willReturn(['personHistory']);
|
|
// motive history
|
|
$normalizer->normalize(Argument::type(MotiveHistory::class), 'json', Argument::type('array'))
|
|
->willReturn(['motiveHistory']);
|
|
$normalizer->normalize(Argument::type(Comment::class), 'json', Argument::type('array'))
|
|
->willReturn(['comment']);
|
|
$normalizer->normalize(Argument::type(AddresseeHistory::class), 'json', Argument::type('array'))
|
|
->willReturn(['addresseeHistory']);
|
|
// null values
|
|
$normalizer->normalize(null, 'json', Argument::type('array'))->willReturn(null);
|
|
|
|
$ticketNormalizer = new TicketNormalizer($this->security->reveal());
|
|
$ticketNormalizer->setNormalizer($normalizer->reveal());
|
|
|
|
return $ticketNormalizer;
|
|
}
|
|
}
|