fix: ensure mandatory services are preselected in edit mode

This commit is contained in:
Björn Fromme
2026-07-10 14:33:09 +02:00
parent 4e26b8acc0
commit 99b6876ce2
4 changed files with 158 additions and 1 deletions
@@ -16,6 +16,7 @@ use App\Form\Model\ParticipantCardDataDto;
use App\Form\Model\ParticipantCardPriceDto;
use App\Model\BookingEditSubmissionResult;
use App\Service\BookingChangeTracker;
use App\Service\BookingConfigurator;
use App\Service\BookingEditContextFactory;
use App\Service\BookingEditDataLoader;
use App\Service\BookingEditDraftManager;
@@ -81,6 +82,16 @@ class IndexControllerTest extends TestCase
->method('isDraftRestored')
->willReturn(false);
$bookingSessionService = $this->createMock(BookingSessionManager::class);
$bookingSessionService->expects($this->once())
->method('saveBookingDto')
->with($request, $bookingDto, BookingDto::MODE_EDIT);
$bookingConfigurator = $this->createMock(BookingConfigurator::class);
$bookingConfigurator->expects($this->once())
->method('preselectDefaultServices')
->with($bookingDto);
$preflightChecker = $this->createMock(BookingEditPreFlightChecker::class);
$preflightChecker->expects($this->once())
->method('findMissingValueLabelsByParticipantIndex')
@@ -96,8 +107,9 @@ class IndexControllerTest extends TestCase
$controller = new TestableIndexController(
$dataLoader,
$this->createMock(BookingEditDraftManager::class),
$this->createMock(BookingSessionManager::class),
$bookingSessionService,
$fingerprintService,
$bookingConfigurator,
$contextFactory,
$preflightChecker,
$this->createMock(BookingEditSubmitter::class),
@@ -170,6 +182,7 @@ class IndexControllerTest extends TestCase
$this->createMock(BookingEditDraftManager::class),
$this->createMock(BookingSessionManager::class),
$fingerprintService,
$this->createMock(BookingConfigurator::class),
$contextFactory,
$preflightChecker,
$this->createMock(BookingEditSubmitter::class),
@@ -253,6 +266,7 @@ class IndexControllerTest extends TestCase
$this->createMock(BookingEditDraftManager::class),
$this->createMock(BookingSessionManager::class),
$fingerprintService,
$this->createMock(BookingConfigurator::class),
$contextFactory,
$preflightChecker,
$submitter,
@@ -335,6 +349,7 @@ class IndexControllerTest extends TestCase
$this->createMock(BookingEditDraftManager::class),
$this->createMock(BookingSessionManager::class),
$fingerprintService,
$this->createMock(BookingConfigurator::class),
$contextFactory,
$preflightChecker,
$submitter,
@@ -526,6 +541,7 @@ class IndexControllerTest extends TestCase
$this->createMock(BookingEditDraftManager::class),
$this->createMock(BookingSessionManager::class),
$fingerprintService,
$this->createMock(BookingConfigurator::class),
$this->createMock(BookingEditContextFactory::class),
$preflightChecker,
$submitter,
@@ -566,6 +582,7 @@ final class TestableIndexController extends IndexController
BookingEditDraftManager $draftService,
BookingSessionManager $bookingSessionService,
BookingChangeTracker $fingerprintService,
BookingConfigurator $bookingService,
BookingEditContextFactory $editContextFactory,
BookingEditPreFlightChecker $preFlightChecker,
BookingEditSubmitter $formSubmitter,
@@ -579,6 +596,7 @@ final class TestableIndexController extends IndexController
$draftService,
$bookingSessionService,
$fingerprintService,
$bookingService,
$editContextFactory,
$preFlightChecker,
$formSubmitter,
@@ -15,6 +15,7 @@ use App\Form\Model\BookingEditContext;
use App\Form\Model\BookingSummaryDto;
use App\Form\Model\ParticipantDto;
use App\Form\Model\ParticipantEditDto;
use App\Service\BookingConfigurator;
use App\Service\BookingEditContextFactory;
use App\Service\BookingEditDataLoader;
use App\Service\BookingEditDraftManager;
@@ -26,6 +27,7 @@ use Carbon\CarbonImmutable;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -126,6 +128,7 @@ class ParticipantControllerTest extends TestCase
$dataLoader,
$draftService,
$contextFactory,
$this->createMock(BookingConfigurator::class),
$bookingSessionService,
$prepopulationService,
$participantFormSupportService,
@@ -145,6 +148,109 @@ class ParticipantControllerTest extends TestCase
$this->assertSame(BookingParticipantType::class, $controller->createdFormTypes[1]);
}
public function testRefreshPreselectsDefaultServicesAndRerendersParticipantForm(): void
{
$request = Request::create('/bookings/42/edit/participants/0/refresh', 'POST');
$user = $this->createUser();
$bookingDto = $this->createBookingDto();
$bookingData = $this->createBooking();
$participant = $bookingDto->participants[0];
$form = $this->createMock(FormInterface::class);
$form->expects($this->once())
->method('handleRequest')
->with($request)
->willReturnSelf();
$form->expects($this->once())
->method('createView')
->willReturn(new FormView());
$dataLoader = $this->createMock(BookingEditDataLoader::class);
$dataLoader->expects($this->once())
->method('fetchBookingData')
->with(42, $user)
->willReturn($bookingData);
$bookingSessionService = $this->createMock(BookingSessionManager::class);
$bookingSessionService->expects($this->once())
->method('getBookingDto')
->with($request, BookingDto::MODE_EDIT)
->willReturn($bookingDto);
$bookingSessionService->expects($this->once())
->method('saveBookingDto')
->with($request, $bookingDto, BookingDto::MODE_EDIT);
$bookingConfigurator = $this->createMock(BookingConfigurator::class);
$bookingConfigurator->expects($this->once())
->method('preselectDefaultServices')
->with($bookingDto);
$participantFormSupportService = $this->createMock(ParticipantFormSupport::class);
$participantFormSupportService->expects($this->once())
->method('ensureParticipantExists')
->with($bookingDto, 0)
->willReturn($participant);
$participantFormSupportService->expects($this->exactly(2))
->method('createParticipantEditDto')
->with($bookingDto, 0)
->willReturn(new ParticipantEditDto($participant, $bookingDto));
$participantFormSupportService->expects($this->exactly(2))
->method('getParticipantFormOptions')
->with($bookingDto, true)
->willReturn([
'booking_context' => $bookingDto,
'body_dimension_ranges' => [
'height_min' => 100,
'height_max' => 250,
'weight_min' => 20,
'weight_max' => 200,
'shoe_size_min' => 20,
'shoe_size_max' => 55,
],
'validation_groups' => false,
]);
$participantFormSupportService->expects($this->once())
->method('collectAndClearNotifications')
->with($bookingDto)
->willReturn([]);
$summaryData = $this->createMock(BookingSummaryDto::class);
$context = new BookingEditContext($bookingDto, $bookingData, null, $summaryData);
$contextFactory = $this->createMock(BookingEditContextFactory::class);
$contextFactory->expects($this->once())
->method('prepareBookingDto')
->with($bookingDto);
$contextFactory->expects($this->once())
->method('createParticipantContext')
->with($bookingDto, $bookingData)
->willReturn($context);
$prepopulationService = new ParticipantDataPrefiller(
$this->createMock(ApiClient::class),
$this->createMock(Crypt::class),
$this->createMock(LoggerInterface::class),
);
$controller = new TestableParticipantController(
$dataLoader,
$this->createMock(BookingEditDraftManager::class),
$contextFactory,
$bookingConfigurator,
$bookingSessionService,
$prepopulationService,
$participantFormSupportService,
$user,
$form,
);
$response = $controller->refreshParticipantForm(42, 0, $request);
$this->assertSame(200, $response->getStatusCode());
$this->assertSame([BookingParticipantType::class, BookingParticipantType::class], $controller->createdFormTypes);
$this->assertSame(['participant_form', 'booking_summary'], $controller->renderedBlocks);
}
private function createUser(): User
{
return new User('[email protected]');
@@ -184,6 +290,11 @@ final class TestableParticipantController extends ParticipantController
public ?string $renderTemplate = null;
/**
* @var list<string>
*/
public array $renderedBlocks = [];
/**
* @var array<string, mixed>
*/
@@ -201,6 +312,7 @@ final class TestableParticipantController extends ParticipantController
BookingEditDataLoader $dataLoader,
BookingEditDraftManager $draftService,
BookingEditContextFactory $editContextFactory,
BookingConfigurator $bookingService,
BookingSessionManager $bookingSessionService,
ParticipantDataPrefiller $prepopulationService,
ParticipantFormSupport $participantFormSupportService,
@@ -213,6 +325,7 @@ final class TestableParticipantController extends ParticipantController
$dataLoader,
$draftService,
$editContextFactory,
$bookingService,
$bookingSessionService,
$prepopulationService,
$participantFormSupportService,
@@ -256,4 +369,14 @@ final class TestableParticipantController extends ParticipantController
return new Response('');
}
/**
* @param array<string, mixed> $parameters
*/
protected function renderBlockView(string $view, string $block, array $parameters = []): string
{
$this->renderedBlocks[] = $block;
return '<div></div>';
}
}