Files
myep/tests/Service/ParticipantCardDataServiceTest.php
T

484 lines
16 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Service;
use App\BusProNet\Model\Room;
use App\BusProNet\Model\Travel;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Service\BookingPriceCalculatorService;
use App\Service\ParticipantCardDataService;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class ParticipantCardDataServiceTest extends TestCase
{
private ParticipantCardDataService $service;
private BookingPriceCalculatorService $priceCalculator;
private ValidatorInterface $validator;
protected function setUp(): void
{
$this->priceCalculator = $this->createMock(BookingPriceCalculatorService::class);
$this->validator = $this->createMock(ValidatorInterface::class);
$this->service = new ParticipantCardDataService($this->priceCalculator, $this->validator);
}
public function testGetCardDataWithFullParticipantData(): void
{
// Create test room
$room = new Room();
$room->id = 1;
$room->label = 'Doppelzimmer';
$room->price = 100.0;
$travel = new Travel();
$travel->rooms = [$room];
// Create participant with full data
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = 'Mustermann';
$participant->assignedRoomId = 1;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
// Mock price calculation
$this->priceCalculator
->expects($this->once())
->method('calculateAllParticipantIndividualPrices')
->with($bookingDto)
->willReturn([450.50]);
$result = $this->service->getCardData($bookingDto, 0);
$this->assertEquals('Max Mustermann', $result['name']);
$this->assertEquals('Doppelzimmer', $result['roomName']);
$this->assertEquals('450,50 €', $result['price']);
}
public function testGetCardDataWithPartialName(): void
{
$travel = new Travel();
$travel->rooms = [];
// Participant with only first name
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = null;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0]);
$result = $this->service->getCardData($bookingDto, 0);
$this->assertEquals('Max', $result['name']);
}
public function testGetCardDataWithNoName(): void
{
$travel = new Travel();
$travel->rooms = [];
// Participant without name
$participant = new ParticipantDto();
$participant->firstName = null;
$participant->lastName = null;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0]);
$result = $this->service->getCardData($bookingDto, 0);
$this->assertEquals('Anmelder:in', $result['name']);
}
public function testGetCardDataWithEmptyName(): void
{
$travel = new Travel();
$travel->rooms = [];
// Participant with empty strings for names
$participant = new ParticipantDto();
$participant->firstName = ' ';
$participant->lastName = ' ';
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0]);
$result = $this->service->getCardData($bookingDto, 0);
$this->assertEquals('Anmelder:in', $result['name']);
}
public function testGetCardDataWithNoRoomAssignment(): void
{
$travel = new Travel();
$travel->rooms = [];
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = 'Mustermann';
$participant->assignedRoomId = null;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0]);
$result = $this->service->getCardData($bookingDto, 0);
$this->assertEquals('Kein Zimmer zugewiesen', $result['roomName']);
}
public function testGetCardDataWithUnknownRoom(): void
{
$travel = new Travel();
$travel->rooms = [];
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = 'Mustermann';
$participant->assignedRoomId = 999; // Non-existent room
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0]);
$result = $this->service->getCardData($bookingDto, 0);
$this->assertEquals('Unbekanntes Zimmer', $result['roomName']);
}
public function testGetCardDataWithZeroPriceAndNoRoom(): void
{
$travel = new Travel();
$travel->rooms = [];
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = 'Mustermann';
$participant->assignedRoomId = null; // No room assigned
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0]);
$result = $this->service->getCardData($bookingDto, 0);
// When no room assigned and price is zero, display dash (incomplete configuration)
$this->assertEquals('-', $result['price']);
}
public function testGetCardDataWithZeroPriceButRoomAssigned(): void
{
// Create test room
$room = new Room();
$room->id = 1;
$room->label = 'Doppelzimmer';
$room->price = 0.0;
$travel = new Travel();
$travel->rooms = [$room];
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = 'Mustermann';
$participant->assignedRoomId = 1; // Room is assigned
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0]);
$result = $this->service->getCardData($bookingDto, 0);
// When room is assigned but price is zero, display formatted zero price
$this->assertEquals('0,00 €', $result['price']);
}
public function testGetCardDataWithInvalidIndex(): void
{
$travel = new Travel();
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [];
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Participant at index 0 does not exist');
$this->service->getCardData($bookingDto, 0);
}
public function testGetAllCardsDataWithMultipleParticipants(): void
{
// Create test rooms
$room1 = new Room();
$room1->id = 1;
$room1->label = 'Einzelzimmer';
$room2 = new Room();
$room2->id = 2;
$room2->label = 'Doppelzimmer';
$travel = new Travel();
$travel->rooms = [$room1, $room2];
// Create participants
$participant1 = new ParticipantDto();
$participant1->firstName = 'Max';
$participant1->lastName = 'Mustermann';
$participant1->assignedRoomId = 1;
$participant2 = new ParticipantDto();
$participant2->firstName = 'Anna';
$participant2->lastName = 'Schmidt';
$participant2->assignedRoomId = 2;
$participant3 = new ParticipantDto();
$participant3->firstName = null;
$participant3->lastName = null;
$participant3->assignedRoomId = 2;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant1, $participant2, $participant3];
// Mock price calculation
$this->priceCalculator
->expects($this->exactly(3))
->method('calculateAllParticipantIndividualPrices')
->with($bookingDto)
->willReturn([450.0, 500.0, 480.0]);
$result = $this->service->getAllCardsData($bookingDto);
$this->assertCount(3, $result);
// First participant
$this->assertEquals('Max Mustermann', $result[0]['name']);
$this->assertEquals('Einzelzimmer', $result[0]['roomName']);
$this->assertEquals('450,00 €', $result[0]['price']);
// Second participant
$this->assertEquals('Anna Schmidt', $result[1]['name']);
$this->assertEquals('Doppelzimmer', $result[1]['roomName']);
$this->assertEquals('500,00 €', $result[1]['price']);
// Third participant (no name)
$this->assertEquals('Teilnehmer:in', $result[2]['name']);
$this->assertEquals('Doppelzimmer', $result[2]['roomName']);
$this->assertEquals('480,00 €', $result[2]['price']);
}
public function testGetAllCardsDataWithEmptyParticipants(): void
{
$travel = new Travel();
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [];
$result = $this->service->getAllCardsData($bookingDto);
$this->assertEmpty($result);
}
public function testPriceFormattingWithLargeAmount(): void
{
$travel = new Travel();
$travel->rooms = [];
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = 'Mustermann';
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([1234.56]);
$result = $this->service->getCardData($bookingDto, 0);
$this->assertEquals('1.234,56 €', $result['price']);
}
public function testFallbackNameIndexingIsOneBasedNotZeroBased(): void
{
$travel = new Travel();
$travel->rooms = [];
$participant1 = new ParticipantDto();
$participant2 = new ParticipantDto();
$participant3 = new ParticipantDto();
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant1, $participant2, $participant3];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0, 0.0, 0.0]);
$result1 = $this->service->getCardData($bookingDto, 0);
$result2 = $this->service->getCardData($bookingDto, 1);
$result3 = $this->service->getCardData($bookingDto, 2);
$this->assertEquals('Anmelder:in', $result1['name']);
$this->assertEquals('Teilnehmer:in', $result2['name']);
$this->assertEquals('Teilnehmer:in', $result3['name']);
}
public function testGetCardDataWithValidationReturnsValidCard(): void
{
$room = new Room();
$room->id = 1;
$room->label = 'Doppelzimmer';
$travel = new Travel();
$travel->rooms = [$room];
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = 'Mustermann';
$participant->assignedRoomId = 1;
$participant->email = '[email protected]';
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([450.50]);
// Mock validator to return no violations (valid)
$violations = $this->createMock(\Symfony\Component\Validator\ConstraintViolationListInterface::class);
$violations->expects($this->once())
->method('count')
->willReturn(0);
$this->validator
->expects($this->once())
->method('validate')
->willReturn($violations);
$result = $this->service->getCardDataWithValidation($bookingDto, 0, ['booking_create']);
$this->assertEquals('Max Mustermann', $result['name']);
$this->assertEquals('Doppelzimmer', $result['roomName']);
$this->assertEquals('450,50 €', $result['price']);
$this->assertTrue($result['isValid']);
$this->assertEmpty($result['errorMessages']);
}
public function testGetCardDataWithValidationReturnsInvalidCard(): void
{
$travel = new Travel();
$travel->rooms = [];
$participant = new ParticipantDto();
$participant->firstName = 'Max';
$participant->lastName = 'Mustermann';
$participant->email = '[email protected]';
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
$this->priceCalculator
->method('calculateAllParticipantIndividualPrices')
->willReturn([0.0]);
// Mock validator to return violations (invalid)
$violation = $this->createMock(\Symfony\Component\Validator\ConstraintViolationInterface::class);
$violation->expects($this->once())
->method('getMessage')
->willReturn('Diese E-Mail Adresse wird bereits von einem anderen Teilnehmer verwendet');
// Use ConstraintViolationList directly instead of mocking
$violations = new \Symfony\Component\Validator\ConstraintViolationList([$violation]);
$this->validator
->expects($this->once())
->method('validate')
->willReturn($violations);
$result = $this->service->getCardDataWithValidation($bookingDto, 0, ['booking_create']);
$this->assertEquals('Max Mustermann', $result['name']);
$this->assertFalse($result['isValid']);
$this->assertCount(1, $result['errorMessages']);
$this->assertEquals('Diese E-Mail Adresse wird bereits von einem anderen Teilnehmer verwendet', $result['errorMessages'][0]);
}
public function testGetAllCardsDataWithValidationReturnsAllCards(): void
{
$room = new Room();
$room->id = 1;
$room->label = 'Doppelzimmer';
$travel = new Travel();
$travel->rooms = [$room];
$participant1 = new ParticipantDto();
$participant1->firstName = 'Max';
$participant1->lastName = 'Mustermann';
$participant1->assignedRoomId = 1;
$participant1->email = '[email protected]';
$participant2 = new ParticipantDto();
$participant2->firstName = 'Anna';
$participant2->lastName = 'Schmidt';
$participant2->assignedRoomId = 1;
$participant2->email = '[email protected]';
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant1, $participant2];
$this->priceCalculator
->expects($this->exactly(2))
->method('calculateAllParticipantIndividualPrices')
->willReturn([450.0, 500.0]);
// Mock validator to return no violations for both participants
$violations = $this->createMock(\Symfony\Component\Validator\ConstraintViolationListInterface::class);
$violations->expects($this->exactly(2))
->method('count')
->willReturn(0);
$this->validator
->expects($this->exactly(2))
->method('validate')
->willReturn($violations);
$result = $this->service->getAllCardsDataWithValidation($bookingDto, ['booking_create']);
$this->assertCount(2, $result);
$this->assertTrue($result[0]['isValid']);
$this->assertTrue($result[1]['isValid']);
$this->assertEquals('Max Mustermann', $result[0]['name']);
$this->assertEquals('Anna Schmidt', $result[1]['name']);
}
}