feat: unique email addresses of participants unless child, cleanup
addresses #869axbn21
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Form\Service;
|
||||
|
||||
use App\BusProNet\Model\Travel;
|
||||
use App\Form\Model\BookingDto;
|
||||
use App\Form\Model\ParticipantDto;
|
||||
use App\Form\Service\ParticipantEmailFieldHandler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ParticipantEmailFieldHandlerTest extends TestCase
|
||||
{
|
||||
private ParticipantEmailFieldHandler $handler;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->handler = new ParticipantEmailFieldHandler();
|
||||
}
|
||||
|
||||
public function testGetFieldName(): void
|
||||
{
|
||||
$this->assertSame('email', $this->handler->getFieldName());
|
||||
}
|
||||
|
||||
public function testGetDependencies(): void
|
||||
{
|
||||
$this->assertSame([], $this->handler->getDependencies());
|
||||
}
|
||||
|
||||
public function testShouldProcessReturnsTrueWhenEmailFieldExists(): void
|
||||
{
|
||||
$this->assertTrue($this->handler->shouldProcess(['email' => '[email protected]'], BookingDto::MODE_CREATE, 0));
|
||||
$this->assertTrue($this->handler->shouldProcess(['email' => null], BookingDto::MODE_EDIT, 5));
|
||||
}
|
||||
|
||||
public function testShouldProcessReturnsFalseWhenEmailFieldMissing(): void
|
||||
{
|
||||
$this->assertFalse($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
|
||||
$this->assertFalse($this->handler->shouldProcess(['firstName' => 'John'], BookingDto::MODE_EDIT, 5));
|
||||
}
|
||||
|
||||
public function testProcessFieldAdultsWithUniqueEmailsNoNotification(): void
|
||||
{
|
||||
$participant1 = $this->createAdultParticipant('[email protected]');
|
||||
$participant2 = $this->createAdultParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertEmpty($participant1->notifications);
|
||||
}
|
||||
|
||||
public function testProcessFieldAdultsWithDuplicateEmailsAddsWarningNotification(): void
|
||||
{
|
||||
$participant1 = $this->createAdultParticipant('[email protected]');
|
||||
$participant2 = $this->createAdultParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertCount(1, $participant1->notifications);
|
||||
$this->assertSame('warning', $participant1->notifications[0]['type']);
|
||||
$this->assertSame(
|
||||
'Diese E-Mail Adresse wird bereits von einem anderen erwachsenen Teilnehmer verwendet',
|
||||
$participant1->notifications[0]['message']
|
||||
);
|
||||
}
|
||||
|
||||
public function testProcessFieldAdultWithSameEmailAsChildNoNotification(): void
|
||||
{
|
||||
$adult = $this->createAdultParticipant('[email protected]');
|
||||
$child = $this->createChildParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$adult, $child];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertEmpty($adult->notifications);
|
||||
}
|
||||
|
||||
public function testProcessFieldChildWithDuplicateEmailNoNotification(): void
|
||||
{
|
||||
$child1 = $this->createChildParticipant('[email protected]');
|
||||
$child2 = $this->createChildParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$child1, $child2];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertEmpty($child1->notifications);
|
||||
}
|
||||
|
||||
public function testProcessFieldChildWithSameEmailAsAdultNoNotification(): void
|
||||
{
|
||||
$adult = $this->createAdultParticipant('[email protected]');
|
||||
$child = $this->createChildParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$adult, $child];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
// Process child participant (index 1)
|
||||
$this->handler->processField($submittedData, $bookingDto, 1);
|
||||
|
||||
$this->assertEmpty($child->notifications);
|
||||
}
|
||||
|
||||
public function testProcessFieldThreeAdultsWithSameEmailAddsNotification(): void
|
||||
{
|
||||
$participant1 = $this->createAdultParticipant('[email protected]');
|
||||
$participant2 = $this->createAdultParticipant('[email protected]');
|
||||
$participant3 = $this->createAdultParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2, $participant3];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertCount(1, $participant1->notifications);
|
||||
$this->assertSame('warning', $participant1->notifications[0]['type']);
|
||||
}
|
||||
|
||||
public function testProcessFieldParticipantWithoutBirthDateTreatedAsAdult(): void
|
||||
{
|
||||
$participant1 = new ParticipantDto();
|
||||
$participant1->dateOfBirth = null; // Unknown age - treated as adult
|
||||
$participant1->email = '[email protected]';
|
||||
|
||||
$participant2 = $this->createAdultParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertCount(1, $participant1->notifications);
|
||||
$this->assertSame('warning', $participant1->notifications[0]['type']);
|
||||
}
|
||||
|
||||
public function testProcessFieldNullEmailSkipsValidation(): void
|
||||
{
|
||||
$participant1 = $this->createAdultParticipant(null);
|
||||
$participant2 = $this->createAdultParticipant(null);
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2];
|
||||
|
||||
$submittedData = ['email' => null];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertEmpty($participant1->notifications);
|
||||
}
|
||||
|
||||
public function testProcessFieldEmptyEmailSkipsValidation(): void
|
||||
{
|
||||
$participant1 = $this->createAdultParticipant('');
|
||||
$participant2 = $this->createAdultParticipant('');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2];
|
||||
|
||||
$submittedData = ['email' => ''];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertEmpty($participant1->notifications);
|
||||
}
|
||||
|
||||
public function testProcessFieldWhitespaceOnlyEmailSkipsValidation(): void
|
||||
{
|
||||
$participant1 = $this->createAdultParticipant(' ');
|
||||
$participant2 = $this->createAdultParticipant(' ');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2];
|
||||
|
||||
$submittedData = ['email' => ' '];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertEmpty($participant1->notifications);
|
||||
}
|
||||
|
||||
public function testProcessFieldCaseInsensitiveEmailComparison(): void
|
||||
{
|
||||
$participant1 = $this->createAdultParticipant('[email protected]');
|
||||
$participant2 = $this->createAdultParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
$this->assertCount(1, $participant1->notifications);
|
||||
$this->assertSame('warning', $participant1->notifications[0]['type']);
|
||||
}
|
||||
|
||||
public function testProcessFieldWithoutParticipant(): void
|
||||
{
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||
|
||||
// Should handle gracefully when participant doesn't exist
|
||||
$this->expectNotToPerformAssertions();
|
||||
}
|
||||
|
||||
public function testProcessFieldWithDifferentParticipantIndex(): void
|
||||
{
|
||||
$participant1 = $this->createAdultParticipant('[email protected]');
|
||||
$participant2 = $this->createAdultParticipant('[email protected]');
|
||||
$participant3 = $this->createAdultParticipant('[email protected]');
|
||||
|
||||
$travel = new Travel();
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->participants = [$participant1, $participant2, $participant3];
|
||||
|
||||
$submittedData = ['email' => '[email protected]'];
|
||||
|
||||
// Process for participant at index 2
|
||||
$this->handler->processField($submittedData, $bookingDto, 2);
|
||||
|
||||
$this->assertEmpty($participant1->notifications); // Should not be affected
|
||||
$this->assertEmpty($participant2->notifications); // Should not be affected
|
||||
$this->assertCount(1, $participant3->notifications); // Should receive warning
|
||||
}
|
||||
|
||||
private function createAdultParticipant(?string $email): ParticipantDto
|
||||
{
|
||||
$participant = new ParticipantDto();
|
||||
$participant->dateOfBirth = new \DateTimeImmutable('1990-01-01'); // Adult (over 18)
|
||||
$participant->email = $email;
|
||||
|
||||
return $participant;
|
||||
}
|
||||
|
||||
private function createChildParticipant(?string $email): ParticipantDto
|
||||
{
|
||||
$participant = new ParticipantDto();
|
||||
$participant->dateOfBirth = new \DateTimeImmutable('2015-01-01'); // Child (under 16)
|
||||
$participant->email = $email;
|
||||
|
||||
return $participant;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user