Refactor NotificationFlagDataMapper to improve handling of null and missing data, and add comprehensive unit tests to verify behavior.

This commit is contained in:
2025-09-09 22:29:56 +02:00
parent 2a280b814f
commit aa64ff02ec
2 changed files with 148 additions and 8 deletions

View File

@@ -28,13 +28,17 @@ final readonly class NotificationFlagDataMapper implements DataMapperInterface
foreach ($this->notificationFlagProviders as $flagProvider) {
$flag = $flagProvider->getFlag();
$data = $viewData[$flag] ?? null;
if (isset($formsArray[$flag])) {
$flagForm = $formsArray[$flag];
$immediateEmailChecked = in_array(User::NOTIF_FLAG_IMMEDIATE_EMAIL, $viewData[$flag] ?? [], true)
|| !array_key_exists($flag, $viewData);
$dailyEmailChecked = in_array(User::NOTIF_FLAG_DAILY_DIGEST, $viewData[$flag] ?? [], true);
$immediateEmailChecked =
null === $data
|| !array_key_exists($flag, $viewData) // true if no data given
|| in_array(User::NOTIF_FLAG_IMMEDIATE_EMAIL, $data, true) // true if 'immediate-email' is present in the array
;
$dailyEmailChecked = is_array($data) && in_array(User::NOTIF_FLAG_DAILY_DIGEST, $data, true);
if ($flagForm->has('immediate_email')) {
$flagForm->get('immediate_email')->setData($immediateEmailChecked);
@@ -49,7 +53,6 @@ final readonly class NotificationFlagDataMapper implements DataMapperInterface
public function mapFormsToData($forms, &$viewData): void
{
$formsArray = iterator_to_array($forms);
$viewData = [];
foreach ($this->notificationFlagProviders as $flagProvider) {
$flag = $flagProvider->getFlag();
@@ -65,10 +68,6 @@ final readonly class NotificationFlagDataMapper implements DataMapperInterface
if (true === $flagForm['daily_email']->getData()) {
$viewData[$flag][] = User::NOTIF_FLAG_DAILY_DIGEST;
}
if ([] === $viewData[$flag]) {
$viewData[$flag][] = User::NOTIF_FLAG_IMMEDIATE_EMAIL;
}
}
}
}

View File

@@ -0,0 +1,141 @@
<?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\MainBundle\Tests\Form\DataMapper;
use Chill\MainBundle\Form\DataMapper\NotificationFlagDataMapper;
use Chill\MainBundle\Notification\FlagProviders\NotificationFlagProviderInterface;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Translation\TranslatableMessage;
/**
* @internal
*
* @coversNothing
*/
class NotificationFlagDataMapperTest extends TestCase
{
use ProphecyTrait;
private function buildDataMapper(): NotificationFlagDataMapper
{
$notificationFlagProvider = new class () implements NotificationFlagProviderInterface {
public function getFlag(): string
{
return 'dummy_flag';
}
public function getLabel(): TranslatableMessage
{
return new TranslatableMessage('');
}
};
return new NotificationFlagDataMapper([$notificationFlagProvider]);
}
/**
* @dataProvider provideDataMapDataToForms
*/
public function testMapDataToForms(?array $viewData, bool $expectedImmediateEmailValue, bool $expectedDailyEmailValue): void
{
$form = $this->prophesize(FormInterface::class);
$formImmediateEmail = $this->prophesize(FormInterface::class);
$formImmediateEmail->setData($expectedImmediateEmailValue)->shouldBeCalled();
$formDailyEmail = $this->prophesize(FormInterface::class);
$formDailyEmail->setData($expectedDailyEmailValue)->shouldBeCalled();
$form->has('immediate_email')->willReturn(true);
$form->get('immediate_email')->willReturn($formImmediateEmail->reveal());
$form->has('daily_email')->willReturn(true);
$form->get('daily_email')->willReturn($formDailyEmail->reveal());
$forms = ['dummy_flag' => $form->reveal()];
$this->buildDataMapper()->mapDataToForms($viewData, $forms);
}
public static function provideDataMapDataToForms(): iterable
{
yield [
['dummy_flag' => ['immediate-email']],
true,
false,
];
yield [
['dummy_flag' => ['daily-digest']],
false,
true,
];
yield [
['dummy_flag' => ['immediate-email', 'daily-digest']],
true,
true,
];
yield [
['dummy_flag' => null],
true,
false,
];
yield [
null,
true,
false,
];
}
/**
* @dataProvider provideDataMapFormsToData
*/
public function testMapFormsToData(bool $immediateEmailValue, bool $dailyDigestValue, array $viewData, array $expected): void
{
$formImmediateEmail = $this->prophesize(FormInterface::class);
$formImmediateEmail->getData()->willReturn($immediateEmailValue)->shouldBeCalled();
$formDailyEmail = $this->prophesize(FormInterface::class);
$formDailyEmail->getData()->willReturn($dailyDigestValue)->shouldBeCalled();
$forms = [
'dummy_flag' => [
'immediate_email' => $formImmediateEmail->reveal(),
'daily_email' => $formDailyEmail->reveal(),
],
];
$this->buildDataMapper()->mapFormsToData($forms, $viewData);
self::assertEqualsCanonicalizing($expected, $viewData);
}
public static function provideDataMapFormsToData(): iterable
{
yield [
true, true, [], ['dummy_flag' => ['immediate-email', 'daily-digest']],
];
yield [
true, false, [], ['dummy_flag' => ['immediate-email']],
];
yield [
false, true, [], ['dummy_flag' => ['daily-digest']],
];
yield [
false, false, [], ['dummy_flag' => []],
];
}
}