feat: admin editable email templates

addresses #869eg7ptr
This commit is contained in:
Björn Fromme
2026-08-17 10:39:19 +02:00
parent 804dab335f
commit 3e08965e48
49 changed files with 1760 additions and 276 deletions
+104
View File
@@ -0,0 +1,104 @@
<?php
declare(strict_types=1);
namespace App\Tests\Form;
use App\Config\EmailTextCatalog;
use App\Config\EmailTextKey;
use App\Entity\EmailText;
use App\Form\EmailTextType;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
class EmailTextTypeTest extends KernelTestCase
{
public function testTheDeliveredWordingIsAcceptedUnchanged(): void
{
self::bootKernel();
$definition = self::getContainer()->get(EmailTextCatalog::class)->get(EmailTextKey::APPLICATION_ACCEPTED);
$form = $this->submit(EmailTextKey::APPLICATION_ACCEPTED, [
'subject' => $definition->defaultSubject,
'headline' => $definition->defaultHeadline,
'body' => $definition->defaultBody,
]);
$this->assertTrue($form->isValid(), (string) $form->getErrors(true));
}
/**
* A typo in a placeholder would otherwise reach a teamer's inbox as a dash, with
* nothing anywhere pointing at the cause.
*/
public function testAnUnknownPlaceholderIsRejected(): void
{
$form = $this->submit(EmailTextKey::APPLICATION_ACCEPTED, [
'body' => 'Dein Einsatz {destinaton} wurde angenommen',
]);
$this->assertFalse($form->isValid());
$this->assertStringContainsString(
'{destinaton}',
(string) $form->get('body')->getErrors()
);
}
/**
* Placeholders are per mail: the rejection mail has no special agreements to print.
*/
public function testAPlaceholderOfAnotherMailIsRejected(): void
{
$form = $this->submit(EmailTextKey::APPLICATION_REJECTED, [
'body' => 'Absprachen: {specialAgreements}',
]);
$this->assertFalse($form->isValid());
}
public function testTheSubjectIsCheckedForPlaceholdersToo(): void
{
$form = $this->submit(EmailTextKey::APPLICATION_REJECTED, [
'subject' => 'Einsatz {unbekannt}',
]);
$this->assertFalse($form->isValid());
}
/**
* A mail may open straight with its text, so the headline is optional.
*/
public function testTheHeadlineMayBeEmpty(): void
{
$form = $this->submit(EmailTextKey::APPLICATION_REJECTED, ['headline' => '']);
$this->assertTrue($form->isValid());
}
/**
* @param array<string, string> $data
*/
private function submit(EmailTextKey $key, array $data): FormInterface
{
self::bootKernel();
$definition = self::getContainer()->get(EmailTextCatalog::class)->get($key);
$form = self::getContainer()
->get(FormFactoryInterface::class)
->create(EmailTextType::class, new EmailText($key), [
'definition' => $definition,
'csrf_protection' => false,
])
;
$form->submit($data + [
'subject' => $definition->defaultSubject,
'headline' => $definition->defaultHeadline,
'body' => $definition->defaultBody,
]);
return $form;
}
}